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 States Laravel Package

spatie/laravel-model-states

Add state and state machine behavior to Laravel Eloquent models. Represent each state as a class, automatically serialize to/from the database, and perform clean, explicit transitions with configurable rules—ideal for workflows like payments, orders, and approvals.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Domain-Driven Design (DDD) Alignment: Enables clean separation of state logic from model logic, improving code organization and maintainability for complex workflows (e.g., order processing, subscriptions, or approval pipelines).

  • State Machine Patterns: Facilitates implementing finite state machines (FSMs) for workflows with clear transitions (e.g., Draft → Published → Archived for content).

  • Build vs. Buy: Avoids reinventing state management wheels; leverages a battle-tested, MIT-licensed package with 1.3K+ stars and active maintenance.

  • Use Cases:

    • Multi-state workflows: Orders (e.g., Pending → Shipped → Delivered), payments (Pending → Paid → Refunded), or user accounts (Active → Suspended → Banned).
    • Dynamic UI/UX: State-dependent UI logic (e.g., disabling buttons or showing tooltips based on Paid vs. Failed states).
    • Validation/Authorization: Restrict transitions (e.g., prevent PaidPending reversals) or enforce business rules (e.g., Failed payments require manual review).
    • Auditability: Track state changes via events (e.g., StateChanged) for compliance or debugging.
    • Internationalization: Localize state names (e.g., PaidPagado) via the $name property.
  • Roadmap Enablers:

    • Scalable Architecture: Decouples state logic from models, easing future refactoring or microservice decomposition.
    • Feature Flags: Use states to gate features (e.g., BetaLive transitions for gradual rollouts).
    • Machine Learning: Log state transitions to train predictive models (e.g., "What causes Failed payments?").

When to Consider This Package

  • Look Elsewhere If:

    • Simple State Logic: Your models only need a single status column (e.g., active/inactive). Use Laravel’s built-in casts or accessors instead.
    • No Transitions: States are static (e.g., UserRole with no workflow). A plain enum or foreignKey relationship suffices.
    • Performance-Critical Paths: Serializing state classes to/from DB adds minor overhead. For high-throughput systems, consider a lightweight state column with raw strings.
    • Non-Laravel Backend: Using Node.js, Python, or another stack. Porting this package may not be worth the effort.
    • Existing State Machine Libraries: Projects already using libraries like symfony/state-machine or egulias/state-machine.
    • Complex State Dependencies: States require cross-model validation (e.g., "Order can’t be Shipped if Inventory is OutOfStock"). Consider a workflow engine like Camunda or custom services.
  • Adopt If:

    • States involve multiple classes/methods (e.g., Paid has color(), Failed has notifyAdmin()).
    • You need transition validation (e.g., "Only admins can transition DraftPublished").
    • States are shared across models (e.g., OrderState reused for Invoice and Shipment).
    • Your team is familiar with state patterns or needs a gentle introduction.

How to Pitch It (Stakeholders)

For Executives/Business Leaders:

"This package lets us model complex workflows—like order processing or payment statuses—as first-class citizens in our codebase. Instead of hacking together status columns or spaghetti logic, we’ll define clear states (e.g., Pending, Paid, Failed) with rules for how they transition. This reduces bugs, makes business logic explicit, and gives us flexibility to change workflows without rewriting core systems. For example, if we need to add a Refunded state to payments, we just create a new class—no database migrations or model refactors. It’s like upgrading from spreadsheets to a proper workflow engine, but with the simplicity of Laravel."

ROI:

  • Faster Development: Reuse state logic across features (e.g., subscriptions, approvals).
  • Lower Risk: Explicit transitions prevent invalid states (e.g., no PaidPending reversals).
  • Scalability: Supports future features like audit logs, state-dependent UI, or ML-driven workflows.

For Engineers/Architects:

*"This is a type-safe, event-driven state machine for Eloquent models, built on Laravel’s ecosystem. It solves the problem of managing complex workflows (e.g., orders, payments, user accounts) by:

  1. Encapsulating state logic: Each state (Paid, Failed) is a class with its own methods (e.g., color(), notify()).
  2. Enforcing transitions: Define allowed transitions (e.g., Pending → Paid) at the model level, with optional validation.
  3. Seamless DB integration: States serialize to a single column (e.g., state = 'paid') but work as objects in code.
  4. Extensibility: Supports custom events, PHP 8 attributes, and directory-based state discovery.

Why not roll our own?

  • Maintenance: Spatie’s package is battle-tested (1.3K stars, active updates) with clear docs.
  • Performance: Minimal overhead (just a cast and a trait).
  • Laravel-native: Integrates with Eloquent, events, and migrations.

Example Use Case: For a subscription system, replace a status column with:

// Model
class Subscription extends Model {
    use HasStates;
    protected $casts = ['state' => SubscriptionState::class];
}

// States
class Active extends SubscriptionState {
    public function canCancel(): bool { return true; }
}

class Cancelled extends SubscriptionState {
    public function canCancel(): bool { return false; }
}

// Transitions
SubscriptionState::config()
    ->allowTransition(Active::class, Cancelled::class)
    ->denyTransition(Cancelled::class, Active::class);

Now, subscription->state->canCancel() is type-safe and transition rules are enforced."*

Trade-offs:

  • Learning Curve: Requires understanding state patterns (but docs/examples are excellent).
  • DB Schema: Adds a state column per model (but this is explicit and intentional).
  • Overhead: ~50ms extra for state resolution (negligible for most apps).
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.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai