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

API zdroje a validácia

use RoundlyConsulting\Lifecycle\Http\Resources\LifecycleResource;
use RoundlyConsulting\Lifecycle\Http\Resources\TransitionRecordResource;

// One response feeds the buttons: state, freeze, expiry and every transition with its reasons
return LifecycleResource::make(Lifecycles::for($listing)->by($request->user()));

// A list: a model stands for its primary lifecycle, with the actor from auth
return LifecycleResource::collection(Listing::query()->withLifecycle()->get());
// Another lifecycle of every model in a list
return LifecycleResource::collectionFor(Order::query()->withLifecycle()->get(), 'payment_status');

// History rows (context and snapshot only on request)
return TransitionRecordResource::collection(Lifecycles::for($listing)->history());
(new TransitionRecordResource($record))->withContext();

LifecycleResource vráti všetko, čo obrazovka potrebuje — handle vytvorte cez by(), aby sa prechody overili pre daného aktéra; ak dostane model, použije jeho primárny cyklus a prihláseného aktéra. collection() vykreslí primárny cyklus každého modelu; collectionFor($models, 'payment_status') vykreslí pomenovaný cyklus. allowed_transitions obsahuje aj zamietnuté prechody s ich dôvodmi, takže rozhranie vykreslí neaktívne tlačidlá s vysvetlením, pole pre dôvod (requires_reason), formulár (payload_fields) aj odpočet (available_at). Časy sú ISO-8601 v UTC; state a to sú surové hodnoty. S withLifecycle() načíta kolekcia stav, zmrazenie, expiráciu a posledný prechod bez dotazu na každý model:

{
  "lifecycle": "status",
  "state": "active",
  "state_label": "Active",
  "terminal": false,
  "entered_at": "2026-10-02T08:00:00+00:00",
  "version": 2,
  "frozen": {"until": "2026-10-05T08:00:00+00:00", "reason": "maintenance"},
  "expiry": {"expires_at": "2026-11-01T08:00:00+00:00", "due_at": "2026-11-04T08:00:00+00:00", "in_grace": false},
  "allowed_transitions": [
    {
      "name": "close", "label": "Close", "to": "closed", "to_label": "Closed", "allowed": false,
      "denials": [{"code": "frozen", "message": "This record is frozen.", "params": {"transition": "Close", "state": "Active"}, "retry_after": null, "errors": []}],
      "requires_reason": false, "payload_fields": [], "available_at": null
    }
  ],
  "last_transition": {
    "id": 2, "kind": "transition", "transition": "publish", "from": "draft", "to": "active",
    "actor": {"type": "App\\Models\\User", "id": 1}, "system": false, "reason": "ready",
    "occurred_at": "2026-10-02T08:00:00+00:00", "reverted": false
  }
}

TransitionRecordResource vráti id, kind, transition, from, to, actor, system, reason, occurred_at a reverted; context a snapshot až po withContext().

Validačné pravidlá

use RoundlyConsulting\Lifecycle\Rules\ValidState;
use RoundlyConsulting\Lifecycle\Rules\ValidTransition;

$request->validate([
    'transition' => ['required', ValidTransition::for($listing)->by($request->user())],
    'target' => ['required', ValidTransition::for($listing, 'status')->by($request->user())->toState()],
    'status' => ['nullable', ValidState::of(Listing::class)],                 // the model's first lifecycle
    'payment' => ['nullable', ValidState::of(new Order, 'payment_status')],
    'filter' => ['nullable', ValidState::of(ListingLifecycle::class)],       // a definition class
]);

ValidTransition spustí celú pipeline vrátane pravidiel pre aktéra a zlyhá so správou každého zamietnutia; toState() validuje cieľový stav namiesto názvu prechodu. ValidState prijme triedu alebo inštanciu modelu (s voliteľným cyklom) alebo triedu definície a vyžaduje deklarovaný stav. Obe sú informatívne ako check() — apply() rozhodne znova pod zámkom.

Zamietnutia ako 422 a Retry-After

use RoundlyConsulting\Lifecycle\Exceptions\TransitionDeniedException;

// A refusal as a 422, with payload errors under their own keys ($request is a FormRequest)
try {
    Lifecycles::for($listing)->by($request->user())->with($request->validated())->apply('reopen');
} catch (TransitionDeniedException $e) {
    throw $e->toValidationException();
}

Odovzdávajte len zvalidovaný vstup, nikdy $request->all(). Prechod payload zvaliduje znova vlastnými rules() a ponechá len tieto kľúče.

toValidationException() majú TransitionDeniedException (pole transition) aj RollbackDeniedException (pole rollback). Obe implementujú HasRetryAfter z toolkitu: retryAfterSeconds() dá hodnotu pre Retry-After pri rate_limited alebo cooldown_active. decision() a denials() vrátia štruktúrované zamietnutie.

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.