### Install Lifecycle for Laravel with Composer and Artisan Source: https://github.com/roundly-consulting/lifecycle-for-laravel/blob/main/README.md Install the package via Composer, publish the lifecycle migrations, and run the migrations. Requires PHP 8.4, Laravel 12 or 13, and SQLite, PostgreSQL, or MySQL/MariaDB. Set LIFECYCLE_KEY_TYPE and LIFECYCLE_ACTOR_KEY_TYPE before migrating if using UUID/ULID keys. ```bash composer require roundly-consulting/lifecycle-for-laravel php artisan vendor:publish --tag="lifecycle-migrations" php artisan migrate ``` -------------------------------- ### Apply transitions and query lifecycle state Source: https://github.com/roundly-consulting/lifecycle-for-laravel/blob/main/README.md Use the Lifecycles facade to apply transitions, check permissions, rollback, and view history. The example shows applying 'publish', checking 'close', applying 'close' with a reason, rolling back, and retrieving history. ```php use RoundlyConsulting\Lifecycle\Facades\Lifecycles; Lifecycles::for($listing)->by($user)->apply('publish'); // draft → active, checked by the Gate Lifecycles::for($listing)->can('close'); // true Lifecycles::for($listing)->because('Sold elsewhere')->apply('close'); Lifecycles::for($listing)->rollback(); // undo the last transition Lifecycles::for($listing)->history(); // who did what, when and why ``` -------------------------------- ### Define a lifecycle with LifecycleBuilder Source: https://github.com/roundly-consulting/lifecycle-for-laravel/blob/main/README.md Define a lifecycle class extending LifecycleDefinition. Use the builder to set states, initial state, TTL, quota, and transitions. The example shows a ListingLifecycle with draft, active, closed, and expired states, a 30-day TTL, a quota of 5 per user, and transitions with abilities and requirements. ```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) // a backed enum: draft, active, closed, expired ->initial(ListingStatus::Draft); $lifecycle->state(ListingStatus::Active) ->ttl('30 days')->expiresVia('expire') ->quota(5, scope: 'user_id'); // at most 5 active listings per user $lifecycle->transition('publish')->from(ListingStatus::Draft)->to(ListingStatus::Active)->ability('publish'); $lifecycle->transition('close')->from(ListingStatus::Active)->to(ListingStatus::Closed)->requiresReason(); $lifecycle->transition('expire')->from(ListingStatus::Active)->to(ListingStatus::Expired)->systemOnly(); } } ``` -------------------------------- ### Attach lifecycle to Eloquent model with HasLifecycle Source: https://github.com/roundly-consulting/lifecycle-for-laravel/blob/main/README.md Use the HasLifecycle trait and implement LifecycleSubject on the model. The lifecycleDefinitions method maps the 'status' attribute to the ListingLifecycle class, and the casts method casts the status to the ListingStatus enum. ```php use RoundlyConsulting\Lifecycle\Concerns\HasLifecycle; use RoundlyConsulting\Lifecycle\Contracts\LifecycleSubject; final class Listing extends Model implements LifecycleSubject { use HasLifecycle; public function lifecycleDefinitions(): array { return ['status' => ListingLifecycle::class]; } protected function casts(): array { return ['status' => ListingStatus::class]; } } ```