---
title: "Definovanie životného cyklu — Lifecycle for Laravel | Roundly"
description: "Deklarujte stavy, počiatočný a koncové stavy a pomenované prechody v triede definície — každá metóda buildera a spôsob validácie."
url: https://roundly-consulting.com/sk/open-source/navody/lifecycle-for-laravel/definovanie-cyklu
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Lifecycle for Laravel](https://roundly-consulting.com/sk/open-source/navody/lifecycle-for-laravel.md)

# Definovanie životného cyklu

Hodí sa pre akýkoľvek Eloquent model so stavom — niekoľko typických cyklov:

| Model | Typický cyklus | Pravidlá |
| --- | --- | --- |
| Objednávka | `pending → paid → shipped, refunded` | stav platby ako druhý cyklus |
| Tiket | `new → open → waiting → resolved` | znovu otvorený najviac 3-krát |
| Inzerát | `draft → active → expired` | vyprší po 30 dňoch, najviac 5 aktívnych na zákazníka |
| Predplatné | `trial → active → grace → cancelled` | obnovené alebo znovu aktivované |
| Žiadosť | `submitted → in review → approved / rejected` | vrátenie do hodiny |

Definícia rozširuje LifecycleDefinition a všetko deklaruje v define(). Stavy sú prípady backed enumu (string alebo int) alebo obyčajné reťazce:

```php
enum ListingStatus: string
{
    case Draft = 'draft';
    case Active = 'active';
    case Closed = 'closed';
    case Expired = 'expired';
    case Archived = 'archived';
}
```

```php
use RoundlyConsulting\Lifecycle\Definition\LifecycleBuilder;
use RoundlyConsulting\Lifecycle\Definition\LifecycleDefinition;

final class ListingLifecycle extends LifecycleDefinition
{
    public function define(LifecycleBuilder $lifecycle): void
    {
        $lifecycle->states(ListingStatus::class)
            ->initial(ListingStatus::Draft)
            ->terminal(ListingStatus::Archived);

        $lifecycle->state(ListingStatus::Active)
            ->ttl('30 days')->grace('3 days')->warnBefore('7 days', '1 day')
            ->expiresVia('expire')
            ->quota(5, scope: 'user_id')
            ->stamps('published_at');

        $lifecycle->transition('publish')
            ->from(ListingStatus::Draft)->to(ListingStatus::Active)
            ->ability('publish')
            ->allowSystem();

        $lifecycle->transition('close')
            ->from(ListingStatus::Active)->to(ListingStatus::Closed)
            ->rules(['note' => 'nullable|string|max:500']);

        $lifecycle->transition('reopen')
            ->from(ListingStatus::Closed)->to(ListingStatus::Active)
            ->maxOccurrences(3)->cooldown('1 hour')->requiresReason()
            ->rules(['note' => 'nullable|string|max:500']);

        $lifecycle->transition('expire')
            ->from(ListingStatus::Active)->to(ListingStatus::Expired)
            ->systemOnly();

        $lifecycle->transition('reactivate')
            ->from(ListingStatus::Expired)->to(ListingStatus::Active);

        $lifecycle->transition('archive')
            ->from('*')->to(ListingStatus::Archived)
            ->irreversible();
    }
}
```

Definícia sa skompiluje raz za proces, zvaliduje — chyby vyhodia InvalidLifecycleDefinitionException so zoznamom všetkých problémov — a potom je nemenná. Trieda sa vytvára cez new, nikdy cez kontajner: závislosti dajte do guardov, handlerov a hookov zadaných názvom triedy, ktoré sa z kontajnera získajú pri každom behu. define() nesmie čítať stav requestu; dynamické hodnoty patria do closures.

## Vygenerovanie definície

make:lifecycle zapíše triedu definície do App\\Lifecycles — malý platný príklad s reťazcovými stavmi alebo prípady backed enumu ako stavy, so začiatkom v prvom prípade:

```bash
php artisan make:lifecycle ListingLifecycle
php artisan make:lifecycle ListingLifecycle --enum="App\Enums\ListingStatus"

# Edit the stubs make:lifecycle uses
php artisan vendor:publish --tag=lifecycle-stubs
```

## LifecycleBuilder

| Metóda | Význam |
| --- | --- |
| `states(ListingStatus::class) / states(['draft', 'active'])` | Všetky prípady backed enumu (string alebo int) alebo zoznam prípadov či reťazcov — nikdy nie zmiešane. |
| `initial($state)` | Stav, v ktorom nový model začína. Práve jeden; nemôže byť koncový. |
| `terminal(...$states)` | Koncové stavy — nič z nich nevedie. |
| `state($state)` | StateBuilder pre nastavenia jedného stavu. |
| `transition('name')` | TransitionBuilder. Názvy: písmená, číslice, \_ . : -, najviac 64 znakov. |
| `guard($guard)` | Guard, ktorý spúšťa každý prechod tohto cyklu, ešte pred vlastnými guardmi prechodu. |
| `label('…'), meta([...])` | Zobrazovaný názov a ľubovoľné metadáta. |

## StateBuilder

| Metóda | Význam |
| --- | --- |
| `label('…' \| fn () => …)` | Zobrazovaný názov. Predvolene label() enumu, ak ho má, inak headline hodnoty, cez prekladač. |
| `ttl('30 days' \| fn (Model $m) => interval\|instant\|null)` | Čas do expirácie od vstupu do stavu. |
| `expiresAtAttribute('ends_at')` | Okamihom expirácie je vlastný datetime stĺpec modelu (null = nikdy). |
| `grace('3 days')` | Ochranná lehota medzi expiráciou a spustením expiračného prechodu. |
| `warnBefore('7 days', '1 day')` | Upozornenia LifecycleExpiring (najviac 16 predstihov). |
| `expiresVia('expire')` | Prechod, ktorý sa spustí pri expirácii. Musí z tohto stavu odchádzať a byť systemOnly() alebo allowSystem(). |
| `quota($max \| fn (Model $m) => int, scope: 'user_id' \| [...], name: null)` | Najviac $max modelov tejto tabuľky v tomto stave na jeden scope. |
| `minDwell('1 hour')` | Minimálny čas v stave, kým ho smú opustiť používateľské prechody. |
| `sealedAfter('14 days')` | Po tomto čase v stave sa stav už nedá opustiť. |
| `stamps('published_at', …)` | Stĺpce, ktoré sa nastavia na „teraz“ pri každom vstupe do stavu prechodom. |
| `onEnter($hook), onExit($hook)` | StateHook (trieda, inštancia alebo closure), ktorý beží v transakcii. |
| `meta([...])` | Ľubovoľné metadáta. |

## TransitionBuilder

| Metóda | Význam |
| --- | --- |
| `from(...$states)` | Zdrojové stavy; '\*' = každý nekoncový stav okrem cieľového. |
| `fromAnyExcept(...$states)` | Zástupný znak bez uvedených stavov. |
| `to($state)` | Cieľový stav. |
| `allowSelf()` | Povolí, aby from obsahovalo to (prechod do toho istého stavu zachová entered\_at aj plány; expirácia z expiresAtAttribute sa riadi atribútom). |
| `systemOnly() / allowSystem()` | Len systémový kód / používatelia aj systémový kód. Bez jedného z nich sa systémový kód odmietne. |
| `requiresActor(), actors(User::class, …), actor(fn (?Model $actor, Model $subject) => bool)` | Pravidlá pre aktéra. |
| `ability('publish')` | Gate ability, overená ako Gate::forUser($actor)->allows('publish', \[$subject, $context\]). |
| `requiresReason(int $minLength = 1)` | Vyžaduje sa dôvod (používateľský kontext). |
| `rules([...], [...messages]), sensitive('card_number', …)` | Validácia payloadu. Ponechajú sa len zvalidované kľúče; citlivé kľúče sa nikdy neukladajú. |
| `when($guard, code: null, message: null)` | Vlastný guard: trieda, inštancia alebo closure. |
| `notBefore('available_from' \| fn (Model $m) => ?instant, offset: null)` | Nepovolené pred daným okamihom. Reťazec je vždy názov atribútu. |
| `notAfter('deadline' \| fn (Model $m) => ?instant, offset: null)` | Nepovolené po danom okamihu. Samotný okamih je ešte povolený. |
| `maxOccurrences(3)` | Na subjekt; počíta sa zo záznamu stavu, takže čistenie histórie ho nikdy nevynuluje. |
| `cooldown('1 hour')` | Minimálny čas medzi dvoma behmi tohto prechodu (používateľský kontext). |
| `rateLimit(10, '1 hour', RateLimitScope::Actor)` | Cez RateLimiter Laravelu; na Actor, Subject alebo ActorAndSubject (volanie bez aktéra sa počíta na subjekt). Aj viac na jeden prechod. Kľúč sa musí zmestiť do limitu cache 250 znakov — veľmi dlhým názvom tried modelov dajte alias v morph mape. |
| `ignoresFreeze(), ignoresSeal(), ignoresMinDwell()` | Výnimky. |
| `handledBy($handler)` | TransitionHandler (trieda, inštancia alebo closure), ktorý beží v transakcii. |
| `irreversible(), reversible(within: '1 hour', withoutCompensation: false)` | Pravidlá rollbacku. |
| `rollbackRequires('ability'), rollbackGuard($guard)` | Kto smie tento prechod vrátiť. |
| `snapshots('price', …)` | Atribúty zachytené pred prechodom a po ňom, obnovené pri rollbacku. |
| `label('…'), meta([...])` | Zobrazovaný názov a ľubovoľné metadáta. |

## Trvania a čas

Trvania sú CarbonInterval, DateInterval alebo reťazce ako '30 days'. Mesiace a roky nikdy nepretečú (31. január + 1 mesiac = 28. február) a dni sú presné (30 dní = 720 hodín aj cez zmenu letného času). Všetky časové údaje balíka sa ukladajú v UTC.

## Validácia v CI

V CI spúšťajte lifecycle:validate --strict. Vypíše každú chybu aj varovanie — nedosiahnuteľné stavy, slepé uličky, nejednoznačné ciele, handlery, ktoré robia prechod nevratným — a pri Model:atribút overí, že stĺpce stampov, atribútu expirácie a scope kvót, ktoré definícia menuje, existujú a že sa kľúč každého prechodu s rate limitom zmestí do limitu cache 250 znakov (rate\_limit\_key\_too\_long):

```bash
php artisan lifecycle:validate --strict
php artisan lifecycle:validate "App\Models\Listing:status"
```

Metódy buildera nikdy nevyhadzujú výnimky: chybný vstup (neplatné trvanie, záporný limit, názov stĺpca, ktorý nie je identifikátor) sa zaznamená ako problém a validátor ich nahlási všetky naraz. Lifecycles::definitions()->validate($class) vráti rovnaký ValidationReport bez vyhodenia výnimky.

## 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](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## 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.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/lifecycle-for-laravel.md)
