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

Flowra Laravel Package

mhqady/flowra

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install & Publish:

    composer require mhqady/flowra
    php artisan vendor:publish --tag=flowra-config --tag=flowra-migrations --tag=flowra-stubs
    php artisan migrate
    
  2. Define a Workflow: Use the Artisan generator to scaffold a workflow:

    php artisan make:flowra-workflow OrderWorkflow
    

    This creates:

    • A migration for workflow states/transitions
    • A Workflow model class
    • A WorkflowService class
  3. Attach to a Model: Add the HasWorkflow trait to your Eloquent model:

    use Mhqady\Flowra\Traits\HasWorkflow;
    
    class Order extends Model
    {
        use HasWorkflow;
        protected $workflowClass = OrderWorkflow::class;
    }
    
  4. First Transition:

    $order = Order::find(1);
    $order->transition('approve'); // Moves from 'draft' to 'approved'
    

Where to Look First

  • Workflow Definition: Edit the generated OrderWorkflow class in app/Flowra/Workflows.
  • State/Transition Logic: Check the define() method in the workflow class.
  • Model Integration: Verify the HasWorkflow trait is properly configured.

Implementation Patterns

Core Workflow Definition

Define states, transitions, and guards in the workflow class:

protected function define(): void
{
    $this->state('draft')
         ->transition('approve')
             ->to('approved')
             ->guard(fn (Order $order) => $order->user->can('approve_orders'))
             ->action(fn (Order $order) => $order->notifyApproval())
         ->transition('reject')
             ->to('rejected')
             ->action(fn (Order $order) => $order->notifyRejection());
}

Common Workflows

  1. State-Based Logic:

    if ($order->is('approved')) {
        $order->fulfill();
    }
    
  2. Transition with Custom Guard:

    $order->transition('approve', guard: new CustomApprovalGuard());
    
  3. Bulk Transitions:

    Order::where('status', 'pending')->transition('approve');
    
  4. State Groups: Define groups in the workflow:

    $this->stateGroup('review', ['draft', 'pending', 'approved']);
    

    Query using:

    Order::inStateGroup('review')->get();
    

Integration Tips

  • Events: Listen to WorkflowTransitioning/WorkflowTransitioned events for side effects.
  • Commands: Use php artisan flowra:export to generate Mermaid diagrams.
  • Testing: Mock workflows with Flowra::fake() in PHPUnit.
  • Dynamic Workflows: Load workflows from the database at runtime:
    $workflow = Flowra::loadWorkflow('dynamic_workflow_id');
    

Gotchas and Tips

Pitfalls

  1. Migration Order:

    • Run flowra:migrate-workflow after publishing migrations.
    • Workflow migrations depend on the statuses table.
  2. State Naming:

    • States are case-sensitive. Use snake_case for consistency.
    • Avoid reserved keywords (e.g., active, created_at).
  3. Guard Failures:

    • Guards throw WorkflowGuardFailedException. Catch and handle gracefully:
      try {
          $order->transition('approve');
      } catch (WorkflowGuardFailedException $e) {
          return back()->withError($e->getMessage());
      }
      
  4. Circular Dependencies:

    • Avoid transitions that create loops (e.g., A → B → A). Use ->unless() to block:
      ->unless(fn () => $order->wasRecentlyApproved())
      

Debugging

  • Diagram Export:

    php artisan flowra:export --workflow=OrderWorkflow --format=mermaid
    

    Visualize workflows to spot misconfigurations.

  • Log Transitions: Enable logging in config/flowra.php:

    'log_transitions' => true,
    
  • SQL Queries: Use DB::enableQueryLog() to inspect generated queries for state/registry operations.

Extension Points

  1. Custom Actions: Extend the WorkflowAction class or use closures:

    ->action(new SendEmailAction())
    
  2. Dynamic Guards: Implement WorkflowGuardContract for reusable logic:

    class AgeGuard implements WorkflowGuardContract
    {
        public function pass($model, string $transition): bool
        {
            return $model->user->age >= 18;
        }
    }
    
  3. State Metadata: Attach metadata to states for UI hints:

    $this->state('draft')
         ->meta(['color' => 'yellow', 'icon' => 'edit']);
    
  4. Workflow Events: Listen for WorkflowLoaded, WorkflowSaved, or WorkflowDeleted events to sync external systems.

Configuration Quirks

  • Default Workflow: Set default_workflow in config/flowra.php to auto-attach workflows to models without explicit config.

  • Registry Retention: Adjust registry_retention_days to limit history size (default: null = unlimited).

  • Concurrency: Use transition() with lockForUpdate() for thread-safe operations:

    $order = Order::lockForUpdate()->find($id);
    $order->transition('approve');
    
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.
make-dev/orca
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle
dmstr/api-platform-utils-bundle
dmstr/api-configuration-bundle
chrisdev/ux-components
baks-dev/finances
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle