Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Model Status Laravel Package

spatie/laravel-model-status

Add status history to any Eloquent model with Spatie’s HasStatuses trait. Set statuses (strings or enums), store reasons/extra info, and retrieve current or previous statuses via convenient helpers like status() and latestStatus().

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package via Composer: composer require spatie/laravel-model-status.
  2. Publish and run the migration: php artisan vendor:publish --provider="Spatie\ModelStatus\ModelStatusServiceProvider" --tag="migrations" followed by php artisan migrate.
  3. Add the HasStatuses trait to any Eloquent model needing status tracking:
    use Spatie\ModelStatus\HasStatuses;
    
    class Order extends Model
    {
        use HasStatuses;
    }
    
  4. Start setting statuses immediately — simplest case:
    $order->setStatus('pending');
    $currentStatus = $order->status(); // Returns \Spatie\ModelStatus\Status instance
    

Implementation Patterns

  • Enum-based statuses: Define a backed enum and use setStatus() for type-safe status transitions:
    enum OrderStatus: string
    {
        case Pending = 'pending';
        case Processing = 'processing';
        case Shipped = 'shipped';
    }
    
    $order->setStatus(OrderStatus::Processing);
    
    And enforce status constraints by implementing statusEnumClass():
    public function statusEnumClass(): ?string
    {
        return OrderStatus::class;
    }
    
  • Status history and auditing: Store contextual reasons on transition:
    $order->setStatus('shipped', 'Courier: Fedex, tracking #FX123');
    
  • Query by current status using scopes:
    // Get all pending orders
    Order::currentStatus('pending')->get();
    
    // Exclude cancelled or delivered orders
    Order::otherCurrentStatus(['cancelled', 'delivered'])->get();
    
  • Bulk operations and conditional logic:
    $order->hasStatus('pending') // true only if latest status matches
    $order->hasEverHadStatus('shipped') // true if *any* history contains shipped
    $order->hasNeverHadStatus('delivered') // useful for onboarding new flows
    
  • Event-driven side effects: Listen for StatusUpdated to trigger notifications, logs, or external syncs:
    Event::listen(function (StatusUpdated $event) {
        if ($event->newStatus->name === 'shipped') {
            dispatch(new ShipOrderJob($event->model));
        }
    });
    

Gotchas and Tips

  • status vs status(): $model->status returns the name (string); $model->status() returns the full Status object (with reason, created_at, etc.). Use the method for inspection.
  • Validation bypass: forceSetStatus() skips isValidStatus() checks entirely — only use in seeders, migrations, or admin actions.
  • Enum edge cases:
    • statusEnum() returns null if no statuses exist, or if the latest status name doesn’t map to the configured enum.
    • Backed enums use their value, unit enums use name. Avoid renames without migration strategy.
  • Performance tip: The trait caches the latest status on model load — avoid calling setStatus() repeatedly in loops. Use statuses() for iteration over large batches.
  • Custom migrations: If you tweak the statuses table (e.g., rename model_id), update model_primary_key_attribute in config/model-status.php.
  • Deletion nuance: deleteStatus('name') removes all instances of that status, not just the latest. Use with caution in audit-sensitive apps.
  • Testing: Mock the StatusUpdated event to test status transition logic without DB writes:
    Event::fake();
    $order->setStatus('shipped');
    Event::assertDispatched(StatusUpdated::class, fn ($e) => $e->newStatus->name === 'shipped');
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport