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

Enumata Laravel Package

norotaro/enumata

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require norotaro/enumata
    

    Ensure your Laravel version is ≥9.x (check composer.json dependencies).

  2. Define a State Machine: Create an enum class (e.g., app/Enums/OrderStatus.php) extending Enumata\StateDefinition:

    namespace App\Enums;
    
    use Enumata\StateDefinition;
    
    class OrderStatus extends StateDefinition
    {
        public static function states(): array
        {
            return [
                'draft' => ['can' => ['submit']],
                'submitted' => ['can' => ['approve', 'reject']],
                'approved' => ['can' => ['cancel']],
                'rejected' => ['can' => []],
                'cancelled' => ['can' => []],
            ];
        }
    }
    
  3. Configure the Model: In your Eloquent model (e.g., app/Models/Order.php), add:

    use Enumata\HasStates;
    
    class Order extends Model
    {
        use HasStates;
    
        protected $stateEnum = OrderStatus::class;
        protected $stateColumn = 'status';
    }
    
  4. First Use Case: Transition a model instance:

    $order = Order::find(1);
    $order->transition('submit'); // Validates and updates state
    

Implementation Patterns

Core Workflows

  1. State Validation: Use canTransition() to check allowed transitions before calling transition():

    if ($order->canTransition('approve')) {
        $order->transition('approve');
    }
    
  2. Bulk State Updates: Leverage updateStates() for batch operations (e.g., cron jobs):

    Order::where('status', 'submitted')
         ->updateStates('approve'); // Requires `force: true` in config
    
  3. Dynamic State Logic: Override getAllowedTransitions() in the model for context-aware rules:

    public function getAllowedTransitions(string $state): array
    {
        $transitions = parent::getAllowedTransitions($state);
        if ($state === 'approved' && $this->isHighPriority()) {
            $transitions[] = 'fast_track';
        }
        return $transitions;
    }
    
  4. Event-Driven Transitions: Hook into stateChanging and stateChanged events:

    protected static function booted()
    {
        static::stateChanging(function ($model, $from, $to) {
            // Log or validate pre-transition
        });
    
        static::stateChanged(function ($model, $from, $to) {
            // Send notifications, update related models
        });
    }
    

Integration Tips

  • API Responses: Return current state in JSON:

    return response()->json([
        'order' => $order,
        'status' => $order->getState(),
        'allowed_actions' => $order->getAllowedTransitions(),
    ]);
    
  • Admin Panels: Use getAllowedTransitions() to dynamically render UI buttons (e.g., with Livewire/Inertia).

  • Testing: Mock state transitions in unit tests:

    $order->shouldReceive('transition')->once()->with('approve');
    $order->transition('approve');
    

Gotchas and Tips

Pitfalls

  1. Column Mismatch: Ensure $stateColumn matches the database column name exactly (case-sensitive). Fix: Verify with Schema::getColumnListing('orders').

  2. Circular Dependencies: Avoid defining states that create loops (e.g., A → B → A). Fix: Use can arrays to explicitly block invalid paths.

  3. Mass Assignment Risks: Never use fill() or update() directly on the state column. Always use transition(). Fix: Add $guarded = ['status'] to your model.

  4. Enum Caching: State definitions are cached. Clear config after changes:

    php artisan config:clear
    

Debugging

  • Transition Errors: Check the exception message for invalid transitions. Enable debug mode:

    config(['enumata.debug' => true]);
    

    Logs will show attempted transitions and allowed states.

  • State Not Found: Verify the enum class is autoloaded (check composer dump-autoload).

Extension Points

  1. Custom Guards: Extend Enumata\StateDefinition to add logic:

    public static function canTransition($from, $to): bool
    {
        if ($from === 'draft' && now()->isAfter('2023-12-31')) {
            return false; // Expired drafts can't be submitted
        }
        return parent::canTransition($from, $to);
    }
    
  2. State Metadata: Attach data to states (e.g., for UI hints):

    public static function states(): array
    {
        return [
            'draft' => [
                'can' => ['submit'],
                'meta' => ['color' => 'gray', 'label' => 'Draft'],
            ],
        ];
    }
    
  3. Database Constraints: Add a foreign key constraint to enforce valid states:

    Schema::table('orders', function (Blueprint $table) {
        $table->string('status')
              ->comment('Valid values: draft, submitted, approved, rejected, cancelled');
    });
    

Config Quirks

  • Force Transitions: Enable force_transitions in config/enumata.php to bypass validation (use sparingly):

    'force_transitions' => env('ENUMATA_FORCE_TRANSITIONS', false),
    

    Warning: Only use for admin overrides or migrations.

  • Nullable States: Set nullable: true in the state definition to allow null values:

    return [
        null => ['can' => ['initialize']],
        // ...
    ];
    
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.
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
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