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

State Bundle Laravel Package

bastsys/state-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require bastsys/state-bundle
    

    Register the bundle in config/app.php under providers:

    Bastsys\StateBundle\StateBundle::class,
    
  2. Basic Usage Define a state machine for an entity (e.g., Order):

    use Bastsys\StateBundle\StateMachine;
    
    class Order
    {
        private $stateMachine;
    
        public function __construct()
        {
            $this->stateMachine = new StateMachine([
                'draft' => ['next' => 'pending'],
                'pending' => ['next' => 'processing', 'prev' => 'draft'],
                'processing' => ['next' => 'completed', 'prev' => 'pending'],
                'completed' => ['prev' => 'processing'],
            ]);
        }
    
        public function transitionToNext()
        {
            $this->stateMachine->transitionToNext();
        }
    
        public function getCurrentState()
        {
            return $this->stateMachine->getCurrentState();
        }
    }
    
  3. First Use Case Validate state transitions in a controller:

    public function processOrder(Order $order)
    {
        if ($order->getCurrentState() === 'pending') {
            $order->transitionToNext(); // Moves to 'processing'
        }
    }
    

Implementation Patterns

Workflows

  1. State-Driven Logic Use state checks to gate features:

    if ($order->getCurrentState() === 'completed') {
        $this->generateInvoice($order);
    }
    
  2. Event-Based Transitions Trigger transitions via events (e.g., OrderProcessed):

    event(new OrderProcessed($order));
    $order->transitionToNext(); // 'processing' → 'completed'
    
  3. Validation Rules Integrate with Laravel validation:

    $validator = Validator::make($request->all(), [
        'status' => Rule::in($order->stateMachine->getAllowedTransitions()),
    ]);
    

Integration Tips

  • Eloquent Models Store state in a database column (e.g., status) and hydrate the StateMachine on model boot:

    protected static function boot()
    {
        parent::boot();
        static::created(function ($model) {
            $model->stateMachine = new StateMachine($model->getStates());
        });
    }
    
  • API Responses Return state metadata in JSON:

    return response()->json([
        'state' => $order->getCurrentState(),
        'allowed_transitions' => $order->stateMachine->getAllowedTransitions(),
    ]);
    
  • Testing Mock state transitions in unit tests:

    $order->stateMachine->setCurrentState('processing');
    $this->assertEquals('processing', $order->getCurrentState());
    

Gotchas and Tips

Pitfalls

  1. State Machine Initialization

    • Issue: Forgetting to initialize the StateMachine with valid states.
    • Fix: Use a factory or model observer to ensure it’s always bootstrapped.
  2. Circular Dependencies

    • Issue: States with bidirectional transitions (e.g., A ↔ B) can cause infinite loops if not handled.
    • Fix: Explicitly define next/prev without mutual recursion.
  3. Database Sync

    • Issue: State changes in memory aren’t persisted.
    • Fix: Override transitionToNext() to save the model:
      public function transitionToNext()
      {
          $this->stateMachine->transitionToNext();
          $this->save(); // Persist state
      }
      

Debugging

  • State Dump Log the current state machine for debugging:

    \Log::debug('State Machine:', $order->stateMachine->toArray());
    
  • Transition Errors Catch InvalidTransitionException for invalid moves:

    try {
        $order->transitionToNext();
    } catch (InvalidTransitionException $e) {
        \Log::error($e->getMessage());
    }
    

Extension Points

  1. Custom Transitions Extend the StateMachine class to add guards:

    class CustomStateMachine extends StateMachine
    {
        public function transitionToNext()
        {
            if (!$this->canTransition()) {
                throw new InvalidTransitionException('Custom guard failed');
            }
            parent::transitionToNext();
        }
    }
    
  2. State Metadata Attach actions or callbacks to states:

    $states = [
        'draft' => [
            'next' => 'pending',
            'actions' => ['notify_admin'],
        ],
    ];
    
  3. Localization Use language arrays for state names:

    $states = [
        'draft' => [
            'next' => 'pending',
            'label' => trans('states.draft'),
        ],
    ];
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity