DI a akcie
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 bucketA 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žéra | Vracia | Akcia | Poznámka |
|---|---|---|---|
for($owner) | CreditsScope | — | Vstupný bod pre jedného vlastníka. |
format($amount, $scale, $rounding, $storedScale) | string | FormatCreditsAction | Nepotrebuje model. |
currency($bucket) | ?Currency | ResolveBucketCurrencyAction | null = bežné kredity. |
balance($owner, $bucket, $at) | int | GetCreditsBalanceAction | Jedna skupina. |
total($owner, $buckets, $at) | int | GetCreditsTotalAction | null = všetky skupiny; zoznam bez duplicít; [] je 0. |
modify($owner, CreditChangeData $data) | Credit | ModifyCreditsAction | So znamienkom; stráži prečerpanie; spúšťa CreditsModified. |
setTo($owner, $amount, $description, $meta, $allowOverdraft, $bucket) | ?Credit | SetCreditsAction | Jeden 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 timeFormatCreditsAction
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 centsResolveBucketCurrencyAction
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_bucketPrejavte 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 kryptomienOdoslaní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.