Modely so životným cyklom
Model so životným cyklom implementuje kontrakt LifecycleSubject, používa trait HasLifecycle a v lifecycleDefinitions() priradí každý atribút cyklu k jeho definícii:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use RoundlyConsulting\Lifecycle\Concerns\HasLifecycle;
use RoundlyConsulting\Lifecycle\Contracts\LifecycleSubject;
final class Listing extends Model implements LifecycleSubject
{
use HasLifecycle;
use SoftDeletes;
protected $guarded = [];
public function lifecycleDefinitions(): array
{
return ['status' => ListingLifecycle::class];
}
protected function casts(): array
{
return ['status' => ListingStatus::class, 'published_at' => 'datetime'];
}
}Nový model začína v počiatočnom stave. Odvtedy sa stav mení len prechodmi:
use Illuminate\Support\Facades\Gate;
use RoundlyConsulting\Lifecycle\Facades\Lifecycles;
Gate::define('publish', fn (User $user, Listing $listing): bool => $listing->user_id === $user->id);
$listing = Listing::query()->create(['user_id' => $user->id]); // status = draft
Lifecycles::for($listing)->by($user)->apply('publish');
$listing->status; // ListingStatus::Active
$listing->published_at; // now
Lifecycles::for($listing)->expiresAt(); // now + 30 days (the sweep runs "expire" 3 days later)Viac cyklov na jeden model
Kľúče sú názvy atribútov; prvý je predvolený cyklus pre Lifecycles::for($model). Jedna trieda definície môže slúžiť viacerým modelom a kvóty počítajú vlastnú tabuľku každého modelu:
final class Order extends Model implements LifecycleSubject
{
use HasLifecycle;
public function lifecycleDefinitions(): array
{
// attribute => definition; the first one is the default lifecycle
return ['status' => OrderLifecycle::class, 'payment_status' => PaymentLifecycle::class];
}
}
Lifecycles::for($order)->apply('pay'); // the first lifecycle (status)
Lifecycles::for($order, 'payment_status')->apply('authorize'); // another oneČo sa deje pri vytvorení
Atribút cyklu s hodnotou NULL dostane počiatočný stav, deklarovaný nepočiatočný stav sa prijme (factories môžu vytvárať subjekty v ľubovoľnom stave) a nedeklarovaná hodnota vyhodí výnimku. Vytvorenie zapíše záznam stavu a riadok histórie initial a naplánuje TTL stavu. Uloženie priamo zmeneného stavu potom vyhodí výnimku — pozri Striktné zápisy a drift.
Čo pridá trait
- Vzťahy: lifecycleStates(), lifecycleHistory(), lifecycleSchedules() a lifecycleLatestTransitions() (MorphMany).
- Skratky: lifecycle(), transition(), transitionTo(), canTransition() a canTransitionTo() — vytvoria rovnaký handle ako Lifecycles::for() a idú cez toho istého manažéra.
- Query scopes: whereState(), whereNotState(), whereExpired(), whereNotExpired(), whereExpiringWithin(), whereInGrace(), whereFrozen(), whereInStateFor() a withLifecycle().
- Hooky modelu: soft delete subjektu pozastaví jeho plány a obnovenie ich znova spustí (obnovenie bez udalostí modelu, napríklad restoreQuietly(), zachytí najbližší sweep); trvalé zmazanie odstráni jeho záznamy, históriu aj plány (history.purge_on_force_delete). Fungujú aj modely bez SoftDeletes.
- Na soft-deleted subjekt nemožno do jeho obnovenia aplikovať prechod ani rollback: kontroly odpovedia subject_trashed a apply() aj rollback() vyhodia SubjectTrashedException.
$listing->transition('close', ['note' => 'Sold elsewhere']); // name, payload, lifecycle
$listing->canTransition('reopen'); // bool
$listing->lifecycle()->by($user)->because('Back in stock')->apply('reopen');
$listing->transitionTo(ListingStatus::Archived);Rezervované názvy
Názvy metód traitu sú na modeli rezervované. Vzťah alebo atribút s názvom lifecycle či transition treba premenovať — alebo skratky vynechajte a použite fasádu (Lifecycles::for($model)), ktorá žiadnu metódu traitu nepotrebuje.
Voliteľný cast
S enginom funguje aj obyčajný enum cast. AsLifecycleState číta stav podľa definície (prípad enumu alebo reťazec) a ukladá len deklarované stavy — nedeklarovaná hodnota vyhodí UnknownStateException:
use RoundlyConsulting\Lifecycle\Casts\AsLifecycleState;
protected function casts(): array
{
return ['status' => AsLifecycleState::class];
}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 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.