NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

Tri rovnocenné vstupné body spúšťajú ten istý kód. Fasáda je najkratšia a odporúčaná voľba. RoundlyConsulting\Credits\CreditsManager — koreň fasády, injektovateľný singleton — poskytuje identické API ako explicitnú závislosť v konštruktore, bez statických volaní:

use RoundlyConsulting\Credits\CreditsManager;

final class RewardSignup
{
    public function __construct(private CreditsManager $credits) {}

    public function __invoke(User $user): void
    {
        $this->credits->for($user)->bucket('points')->add(100, 'Welcome');
    }
}

Manažér má aj ploché metódy, ktorými sa končí každý scope:

use RoundlyConsulting\Credits\DataTransferObjects\CreditChangeData;

$credits->modify($user, new CreditChangeData(amount: -30, description: 'purchase', bucket: 'points'));
$credits->setTo($user, 500, 'manual adjustment');
$credits->balance($user, bucket: 'points');
$credits->total($user, ['promotional', 'purchased']);           // null = every bucket

A každá operácia je jednoúčelová akcia s jedinou metódou execute() pre prípady, keď ju chcete vytvoriť a spustiť sami — z jobu, príkazu alebo vlastnej akcie:

use RoundlyConsulting\Credits\Actions\{FormatCreditsAction, GetCreditsBalanceAction,
    GetCreditsTotalAction, ModifyCreditsAction, ResolveBucketCurrencyAction, SetCreditsAction};

app(ModifyCreditsAction::class)->execute($user, new CreditChangeData(amount: -30, description: 'purchase'));
app(SetCreditsAction::class)->execute($user, 500, 'manual adjustment');
app(GetCreditsBalanceAction::class)->execute($user, bucket: 'points');
app(GetCreditsTotalAction::class)->execute($user, ['promotional', 'purchased']);
app(FormatCreditsAction::class)->execute(123450, scale: 2);
app(ResolveBucketCurrencyAction::class)->execute('store_credit');

Metóda fasády → akcia

Metóda fasády / manažéraVraciaAkciaPoznámka
for($owner)CreditsScope—Vstupný bod pre jedného vlastníka.
format($amount, $scale, $rounding, $storedScale)stringFormatCreditsActionNepotrebuje model.
currency($bucket)?CurrencyResolveBucketCurrencyActionnull = bežné kredity.
balance($owner, $bucket, $at)intGetCreditsBalanceActionJedna skupina.
total($owner, $buckets, $at)intGetCreditsTotalActionnull = všetky skupiny; zoznam bez duplicít; [] je 0.
modify($owner, CreditChangeData $data)CreditModifyCreditsActionSo znamienkom; stráži prečerpanie; spúšťa CreditsModified.
setTo($owner, $amount, $description, $meta, $allowOverdraft, $bucket)?CreditSetCreditsActionJeden rozdielový záznam; null, ak už sedí.
fake()CreditsFake—Statická, na fasáde — pozrite Testovanie.

Manažér si každú akciu pri každom volaní vytvorí z kontajnera, takže vlastnou implementáciou akcie zmeníte správanie bez forku balíka. Credits::fake() nahradí aj každý injektovaný CreditsManager — vrátane metód HasCredits a credits:modify.

ModifyCreditsAction

Zaznamená jeden záznam v databázovej transakcii: vezme zámok vlastníka (zvýši jeho riadok v credit_locks), načíta zostatok skupiny pod zámkom riadkov, uplatní ochranu pred prečerpaním, pridá záznam a spustí CreditsModified so zostatkom, ktorý zmena vytvorila. Prijíma CreditChangeData:

use RoundlyConsulting\Credits\DataTransferObjects\CreditChangeData;

$change = new CreditChangeData(amount: 50, description: 'top-up');

$change->resolvedBucket(); // 'default' — config('credits.default_bucket') when bucket is null
$change->toAttributes();   // ['amount' => 50, 'description' => 'top-up', 'meta' => null, 'bucket' => 'default']

SetCreditsAction

Nastaví jednu skupinu na presnú sumu cez ModifyCreditsAction. Vezme zámok vlastníka a zostatok načíta pod zámkom riadkov v tej istej transakcii ako zápis, takže súbežné volania sa zoradia za sebou; pri nulovom rozdiele vráti null:

// execute(Model&Creditable $creditable, int $amount, ?string $description = null,
//         ?array $meta = null, bool $allowOverdraft = false, ?string $bucket = null): ?Credit
app(SetCreditsAction::class)->execute($user, 500, 'adjustment', null, false, 'promotional');

GetCreditsBalanceAction

Sčíta záznamy jednej skupiny. V rámci vlastnej transakcie odovzdajte lockForUpdate: true a čítanie prebehne pod zámkami riadkov — rovnako ako pri ochrane pred prečerpaním:

// execute(Model&Creditable $creditable, ?CarbonInterface $at = null, bool $lockForUpdate = false, ?string $bucket = null): int
app(GetCreditsBalanceAction::class)->execute($user, at: now()->subWeek(), bucket: 'promotional');

GetCreditsTotalAction

Sčíta viacero skupín alebo všetky skupiny vlastníka:

// execute(Model&Creditable $creditable, ?array $buckets = null, ?CarbonInterface $at = null): int
$total = app(GetCreditsTotalAction::class);

$total->execute($user, ['promotional', 'purchased']);   // de-duplicated; [] returns 0
$total->execute($user);                                  // null = every bucket
$total->execute($user, at: now()->subWeek());            // ... at a point in time

FormatCreditsAction

Jadro formátovania za Credits::format() a pomocníkmi zobrazenia — tenká vrstva nad MinorUnits::rescale() a MinorUnits::toDecimal() z money-for-laravel. $storedScale je predvolene credits.scale; skupina v mene odovzdá exponent svojej meny:

use RoundlyConsulting\Credits\Actions\FormatCreditsAction;

// execute(int $amount, ?int $scale = null, ?\RoundingMode $rounding = null, ?int $storedScale = null): string
app(FormatCreditsAction::class)->execute(150, scale: 2, rounding: \RoundingMode::HalfEven); // "1.50" (credits.scale = 2)
app(FormatCreditsAction::class)->execute(1050, storedScale: 2);                            // "10.50" — read as cents

ResolveBucketCurrencyAction

Pri každom volaní zistí menu skupiny z credits.currencies podľa registra money. Pomocníky pre Money pri skupine, pre ktorú vráti null, vyhodia BucketNotDenominatedException:

use RoundlyConsulting\Credits\Actions\ResolveBucketCurrencyAction;

// execute(?string $bucket = null): ?Currency
app(ResolveBucketCurrencyAction::class)->execute('store_credit'); // ?Currency — null for a plain bucket
app(ResolveBucketCurrencyAction::class)->execute();               // null = credits.default_bucket

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.