Skip to content

YAML Configuration

Jean-Marc Strauven edited this page Aug 6, 2025 · 2 revisions

πŸ“„ YAML Configuration

This guide covers the complete YAML syntax for defining state machines in Laravel Statecraft. YAML files provide a clean, readable way to define your state machine logic.

πŸ“ File Location

State machine YAML files are stored in:

resources/state-machines/
β”œβ”€β”€ OrderStateMachine.yaml
β”œβ”€β”€ UserStateMachine.yaml
└── ArticleStateMachine.yaml

πŸ—οΈ Basic Structure

Every state machine YAML file follows this basic structure:

name: StateMachineName
model: App\Models\ModelName
initial_state: initial_state_name
field: status  # Optional: custom field name (defaults to 'status')

states:
  - name: state_one
    description: Description of state one
  - name: state_two
    description: Description of state two

transitions:
  - name: transition_name
    from: source_state
    to: target_state
    guard: GuardClass
    action: ActionClass

🎯 State Machine Properties

Required Properties

name

The unique identifier for your state machine:

name: OrderStateMachine

model

The Eloquent model class this state machine applies to:

model: App\Models\Order

initial_state

The default state for new model instances:

initial_state: pending

Optional Properties

field

The database column that stores the current state (defaults to status):

field: current_status

description

Human-readable description of the state machine:

description: "Manages the complete order lifecycle from creation to delivery"

πŸ”„ States Configuration

Simple State List

For basic state machines, use a simple array:

states: [draft, pending, approved, rejected, completed]

Detailed State Objects

For more complex state machines with metadata:

states:
  - name: pending
    description: Order is awaiting payment
    metadata:
      color: yellow
      icon: clock
      
  - name: paid
    description: Payment has been processed
    metadata:
      color: green
      icon: check-circle
      
  - name: cancelled
    description: Order was cancelled by customer
    metadata:
      color: red
      icon: x-circle
      final: true  # Mark as final state

State Metadata

Add custom metadata to states for UI rendering or business logic:

states:
  - name: processing
    description: Order is being processed
    metadata:
      estimated_duration: 24  # hours
      requires_notification: true
      department: fulfillment

⚑ Transitions Configuration

Basic Transition

transitions:
  - name: pay
    from: pending
    to: paid

Transition with Guard

transitions:
  - name: approve
    from: pending
    to: approved
    guard: ManagerGuard

Transition with Action

transitions:
  - name: ship
    from: paid
    to: shipped
    action: CreateShipmentAction

Transition with Both Guard and Action

transitions:
  - name: process_payment
    from: pending
    to: paid
    guard: PaymentValidationGuard
    action: ProcessPaymentAction

Multiple Source States

Allow transitions from multiple states:

transitions:
  - name: cancel
    from: [pending, paid, processing]
    to: cancelled
    action: RefundPaymentAction

Transition Metadata

Add metadata for UI or business logic:

transitions:
  - name: expedite
    from: processing
    to: expedited
    guard: IsVIPCustomer
    action: ExpediteOrder
    metadata:
      cost: 25.00
      description: "Rush processing for VIP customers"
      requires_approval: false

πŸ›‘οΈ Guards Configuration

Simple Guard

Reference a guard class:

guard: PaymentGuard

Method-based Guard

Use a method from your model:

guard: canBeShipped  # Calls $model->canBeShipped()

Complex Guard Expressions

Combine multiple guards with logical operators:

AND Logic

All guards must pass:

guard:
  and:
    - IsManager
    - HasMinimumAmount
    - not: IsBlacklisted

OR Logic

At least one guard must pass:

guard:
  or:
    - IsAdmin
    - IsOwner
    - IsVIPCustomer

Mixed Logic

Combine AND/OR logic:

guard:
  and:
    - or:
        - IsManager
        - IsAdmin
    - HasValidPayment
    - not: IsBlacklisted

Inline Guard Expressions

Define simple conditions inline:

guard: "amount > 100"  # Simple expression

βš™οΈ Actions Configuration

Simple Action

Reference an action class:

action: SendEmailAction

Method-based Action

Use a method from your model:

action: sendNotification  # Calls $model->sendNotification()

Multiple Actions

Execute multiple actions in sequence:

action:
  - ProcessPaymentAction
  - SendConfirmationEmail
  - UpdateInventory

Action with Parameters

Pass parameters to actions:

action:
  class: SendEmailAction
  parameters:
    template: order_confirmation
    priority: high

πŸ“‹ Complete Example

Here's a comprehensive order workflow example:

name: OrderWorkflow
model: App\Models\Order
initial_state: draft
field: status
description: "Complete e-commerce order processing workflow"

states:
  - name: draft
    description: Order is being created
    metadata:
      editable: true
      
  - name: pending
    description: Order is awaiting payment
    metadata:
      color: yellow
      
  - name: paid
    description: Payment has been processed
    metadata:
      color: blue
      
  - name: processing
    description: Order is being fulfilled
    metadata:
      color: orange
      estimated_duration: 24
      
  - name: shipped
    description: Order has been shipped
    metadata:
      color: purple
      
  - name: delivered
    description: Order has been delivered
    metadata:
      color: green
      final: true
      
  - name: cancelled
    description: Order was cancelled
    metadata:
      color: red
      final: true
      
  - name: returned
    description: Order was returned
    metadata:
      color: gray
      final: true

transitions:
  - name: submit
    from: draft
    to: pending
    guard:
      and:
        - hasValidItems
        - hasShippingAddress
    action: notifyPaymentDue
    
  - name: pay
    from: pending
    to: paid
    guard:
      and:
        - PaymentGuard
        - not: IsBlacklisted
    action:
      - ProcessPaymentAction
      - SendConfirmationEmail
    metadata:
      requires_payment: true
      
  - name: process
    from: paid
    to: processing
    guard: hasInventory
    action:
      - ReserveInventory
      - NotifyWarehouse
      
  - name: ship
    from: processing
    to: shipped
    guard:
      and:
        - isPackaged
        - hasShippingLabel
    action:
      - CreateShipment
      - SendTrackingInfo
      
  - name: deliver
    from: shipped
    to: delivered
    action:
      - MarkAsDelivered
      - SendDeliveryConfirmation
      
  - name: cancel
    from: [draft, pending, paid]
    to: cancelled
    action:
      - RefundPayment
      - SendCancellationEmail
      
  - name: return
    from: delivered
    to: returned
    guard: isWithinReturnPeriod
    action:
      - ProcessReturn
      - InitiateRefund

πŸ”§ Advanced Features

Conditional Transitions

Use complex conditions:

transitions:
  - name: auto_approve
    from: pending
    to: approved
    guard:
      and:
        - "amount < 1000"
        - IsRegularCustomer
        - not: RequiresManualReview

Nested State Machines

Reference other state machines:

states:
  - name: payment_processing
    description: Processing payment
    sub_state_machine: PaymentStateMachine

Time-based Transitions

Configure automatic transitions:

transitions:
  - name: auto_cancel
    from: pending
    to: cancelled
    trigger: timeout
    delay: 24h  # Cancel after 24 hours
    action: SendTimeoutNotification

βœ… Validation

Laravel Statecraft validates your YAML configuration. Common validation rules:

  • All referenced states must be defined
  • Transitions must reference valid states
  • Guard and action classes must exist
  • No circular dependencies
  • Initial state must be defined

Use the validation command:

php artisan statecraft:validate OrderWorkflow

πŸš€ What's Next?

Now that you understand YAML configuration:

  1. Learn Guards & Actions - Implement business logic
  2. Explore Examples - See complete workflows
  3. Set up Events - Handle state change notifications
  4. Test Your State Machine - Ensure everything works

Need help with complex workflows? Check out our examples collection for real-world implementations.

Clone this wiki locally