Skip to content

Understanding YAML Flows

Jean-Marc Strauven edited this page Aug 6, 2025 · 1 revision

πŸ“„ Understanding YAML Flows

← Your First Flow | Home | YAML Flow Structure β†’

YAML flows are the heart of Laravel Flowpipe. This page explains how to read, write, and understand YAML workflow definitions.

🧠 Core Concept

Laravel Flowpipe transforms business processes into declarative YAML files. Instead of writing procedural code, you describe what should happen, and Laravel Flowpipe handles how it happens.

Traditional Approach vs. Flowpipe

// Traditional Laravel Code
public function registerUser(Request $request)
{
    $validated = $request->validate([...]);
    
    if (User::where('email', $validated['email'])->exists()) {
        throw new Exception('Email exists');
    }
    
    $user = User::create($validated);
    Mail::to($user)->send(new WelcomeEmail($user));
    
    return $user;
}
# Laravel Flowpipe YAML
flow: user-registration
description: Register a new user

steps:
  - type: action
    class: ValidateInputStep
  - type: action  
    class: CheckEmailUniqueStep
  - type: action
    class: CreateUserStep
  - type: action
    class: SendWelcomeEmailStep

πŸ“‹ Basic YAML Structure

Every YAML flow file has this basic structure:

# Flow metadata
flow: flow-name
description: What this flow does

# Initial data (optional)
send:
  key: value
  another_key: another_value

# The workflow steps
steps:
  - type: action
    name: step-name
    class: StepClassName
    description: What this step does

πŸ”§ Flow Metadata

Required Fields

flow: user-registration           # Unique flow identifier
description: Register new users   # Human-readable description

Optional Fields

version: "1.0"                   # Flow version
tags: [user, registration]       # Categories/tags
timeout: 300                     # Max execution time (seconds)

πŸ“¦ Initial Data (send)

The send section defines the data that flows through your workflow:

send:
  # Simple values
  name: "John Doe"
  email: "[email protected]"
  
  # Complex data
  user_data:
    profile:
      age: 30
      country: "US"
    preferences:
      newsletter: true
      notifications: false
  
  # Arrays
  items:
    - name: "Product A"
      price: 25.99
    - name: "Product B"  
      price: 15.50

πŸ—οΈ Step Types

Laravel Flowpipe supports several step types:

1. Action Steps

Execute PHP classes that implement FlowStep:

steps:
  - type: action
    name: validate-input
    class: App\Steps\ValidateInputStep
    description: Validate user input

2. Closure Steps

Execute inline PHP closures:

steps:
  - type: closure
    name: transform-data
    action: uppercase_name
    description: Convert name to uppercase

3. Group Steps

Execute reusable step collections:

steps:
  - type: group
    name: user-validation
    description: Validate user data

4. Nested Steps

Create sub-workflows:

steps:
  - type: nested
    name: payment-processing
    description: Process payment securely
    steps:
      - type: action
        class: ValidatePaymentStep
      - type: action
        class: ChargeCardStep

πŸ”€ Conditional Execution

Add conditional logic to your flows:

steps:
  - type: action
    class: ProcessOrderStep
    
  - condition:
      field: order_total
      operator: greater_than
      value: 100
    then:
      - type: action
        class: ApplyDiscountStep
    else:
      - type: action
        class: AddShippingFeeStep

Available Operators

  • equals, not_equals
  • greater_than, less_than
  • greater_than_or_equal, less_than_or_equal
  • contains, not_contains
  • in, not_in
  • exists, not_exists

πŸ”„ Loops and Iteration

Process arrays of data:

steps:
  - type: foreach
    name: process-items
    array: items
    steps:
      - type: action
        class: ValidateItemStep
      - type: action
        class: ProcessItemStep

πŸŽ›οΈ Step Configuration

Customize step behavior:

steps:
  - type: action
    name: api-call
    class: ApiCallStep
    description: Call external API
    
    # Step-specific configuration
    config:
      timeout: 30
      retry_attempts: 3
      endpoint: "https://api.example.com"
    
    # Error handling
    on_error: continue  # or "stop", "retry"
    
    # Conditional execution
    when:
      field: api_enabled
      operator: equals
      value: true

πŸ“Š Real-World Example

Here's a complete e-commerce order processing flow:

flow: ecommerce-order-processing
description: Complete order processing workflow
version: "2.1"
tags: [ecommerce, orders, payment]

send:
  order_id: 12345
  items:
    - sku: "PROD-001"
      quantity: 2
      price: 29.99
    - sku: "PROD-002"
      quantity: 1
      price: 15.50
  customer:
    id: 67890
    email: "[email protected]"
  payment_method: "credit_card"

steps:
  # Validation phase
  - type: group
    name: order-validation
    description: Validate order data and inventory
  
  # Inventory check
  - type: foreach
    name: check-inventory
    array: items
    steps:
      - type: action
        class: CheckStockStep
        config:
          reserve_items: true
  
  # Payment processing
  - type: nested
    name: payment-processing
    description: Secure payment processing
    steps:
      - type: action
        class: ValidatePaymentMethodStep
        
      - type: action
        class: CalculateChargesStep
        
      - condition:
          field: order_total
          operator: greater_than
          value: 0
        then:
          - type: action
            class: ProcessPaymentStep
            config:
              timeout: 45
              retry_attempts: 2
  
  # Fulfillment
  - condition:
      field: payment_status
      operator: equals
      value: "successful"
    then:
      - type: action
        class: CreateShipmentStep
      - type: action
        class: SendConfirmationEmailStep
    else:
      - type: action
        class: CancelOrderStep
      - type: action
        class: SendFailureNotificationStep

🎯 Best Practices

1. Use Descriptive Names

# Good
- type: action
  name: validate-user-email
  class: ValidateEmailStep
  description: Check email format and domain

# Avoid
- type: action
  name: step1
  class: Step1

2. Group Related Steps

# Use groups for related functionality
- type: group
  name: user-validation
  description: Complete user data validation

- type: group  
  name: payment-processing
  description: Handle payment workflow

3. Add Meaningful Descriptions

steps:
  - type: action
    name: check-inventory
    class: InventoryCheckStep
    description: Verify product availability and reserve items for 10 minutes

4. Handle Edge Cases

- type: action
  class: ApiCallStep
  on_error: retry
  config:
    retry_attempts: 3
    timeout: 30
  when:
    field: api_enabled
    operator: equals
    value: true

πŸ” YAML Tips

Comments

# This is a comment
flow: my-flow  # Inline comment
description: >
  Multi-line description
  that spans several lines

Multi-line Strings

description: |
  This is a literal multi-line string.
  Line breaks are preserved.
  
query: >
  This is a folded multi-line string.
  Line breaks become spaces.

Anchors and References

# Define reusable configuration
default_timeout: &timeout 30

steps:
  - type: action
    class: Step1
    config:
      timeout: *timeout  # References the anchor
      
  - type: action
    class: Step2  
    config:
      timeout: *timeout  # Reuses the same value

🎯 What's Next?

Now that you understand YAML flows, explore these advanced topics:

πŸš€ Laravel Flowpipe

🏠 Home

🏁 Getting Started

πŸ“š Core Concepts

πŸš€ Advanced Features

πŸ› οΈ Tools & Configuration

πŸ“– Examples


πŸ”— GitHub Repository

Clone this wiki locally