Skip to content

Step Groups

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

πŸ”— Step Groups

← PHP Steps | Home | Error Handling β†’

Step Groups allow you to organize related steps into reusable components. They're the building blocks for creating modular, maintainable workflows.

🧠 Core Concept

A Step Group is a collection of steps defined in a separate YAML file that can be referenced and reused across multiple flows. Think of them as functions for your workflows.

Without Groups (Repetitive)

# user-registration.yaml
steps:
  - type: action
    class: ValidateEmailStep
  - type: action
    class: ValidatePasswordStep
  - type: action
    class: CheckEmailUniqueStep

# user-update.yaml  
steps:
  - type: action
    class: ValidateEmailStep
  - type: action
    class: ValidatePasswordStep
  - type: action
    class: CheckEmailUniqueStep

With Groups (Reusable)

# groups/user-validation.yaml
group: user-validation
description: Comprehensive user input validation

steps:
  - type: action
    class: ValidateEmailStep
  - type: action
    class: ValidatePasswordStep
  - type: action
    class: CheckEmailUniqueStep

# flows/user-registration.yaml
steps:
  - type: group
    name: user-validation

# flows/user-update.yaml
steps:
  - type: group
    name: user-validation

πŸ“ Group File Structure

Groups are stored in the groups/ directory (configurable):

groups/
β”œβ”€β”€ user-validation.yaml
β”œβ”€β”€ payment-processing.yaml
β”œβ”€β”€ inventory-management.yaml
β”œβ”€β”€ notifications.yaml
└── order-fulfillment.yaml

πŸ“‹ Group Definition Syntax

Basic Group Structure

group: group-name
description: What this group does
version: "1.0"                    # Optional
tags: [validation, user]          # Optional

steps:
  - type: action
    name: step-1
    class: Step1Class
    
  - type: action
    name: step-2
    class: Step2Class

Complete Example

# groups/user-validation.yaml
group: user-validation
description: Comprehensive user input validation with security checks
version: "2.1"
tags: [validation, security, user]

steps:
  # Email validation
  - type: action
    name: validate-email-format
    class: App\Flowpipe\Steps\ValidateEmailFormatStep
    description: Check email format and domain
    
  # Password strength validation
  - type: action
    name: validate-password-strength
    class: App\Flowpipe\Steps\ValidatePasswordStrengthStep
    description: Ensure password meets security requirements
    config:
      min_length: 8
      require_special_chars: true
      require_numbers: true
    
  # Check for existing user
  - type: action
    name: check-email-uniqueness
    class: App\Flowpipe\Steps\CheckEmailUniquenessStep
    description: Verify email is not already registered
    
  # Terms acceptance validation
  - type: action
    name: validate-terms-acceptance
    class: App\Flowpipe\Steps\ValidateTermsAcceptanceStep
    description: Ensure user has accepted terms and conditions

🎯 Using Groups in Flows

Basic Usage

# flows/user-registration.yaml
flow: user-registration
description: Complete user registration process

send:
  name: "John Doe"
  email: "[email protected]"
  password: "SecurePassword123!"
  terms_accepted: true

steps:
  # Use the validation group
  - type: group
    name: user-validation
    
  # Continue with registration-specific steps
  - type: action
    name: create-user-account
    class: App\Flowpipe\Steps\CreateUserAccountStep
    
  - type: action
    name: send-welcome-email
    class: App\Flowpipe\Steps\SendWelcomeEmailStep

Group with Configuration

steps:
  - type: group
    name: payment-processing
    description: Process payment with custom settings
    config:
      gateway: stripe
      currency: USD
      timeout: 45
      retry_attempts: 3

Conditional Groups

steps:
  - type: group
    name: premium-user-setup
    when:
      field: user_type
      operator: equals
      value: premium
      
  - type: group
    name: basic-user-setup
    when:
      field: user_type
      operator: equals
      value: basic

πŸ”§ Advanced Group Features

Nested Groups

Groups can reference other groups:

# groups/complete-order-processing.yaml
group: complete-order-processing
description: Full order processing workflow

steps:
  # Validation phase
  - type: group
    name: order-validation
    
  # Business logic phase
  - type: group
    name: inventory-management
    
  - type: group
    name: payment-processing
    
  # Fulfillment phase
  - type: group
    name: order-fulfillment
    
  # Communication phase
  - type: group
    name: customer-notifications

Parameterized Groups

Groups can accept parameters through configuration:

# groups/email-notifications.yaml
group: email-notifications
description: Send various email notifications

steps:
  - type: action
    name: prepare-email-data
    class: App\Flowpipe\Steps\PrepareEmailDataStep
    config:
      template: "{{ config.template | default: 'default' }}"
      subject: "{{ config.subject }}"
      
  - type: action
    name: send-email
    class: App\Flowpipe\Steps\SendEmailStep
    config:
      provider: "{{ config.provider | default: 'default' }}"
      priority: "{{ config.priority | default: 'normal' }}"

Usage:

steps:
  - type: group
    name: email-notifications
    config:
      template: "welcome-email"
      subject: "Welcome to our platform!"
      provider: "sendgrid"
      priority: "high"

Conditional Steps within Groups

# groups/payment-processing.yaml
group: payment-processing
description: Payment processing with multiple providers

steps:
  - type: action
    name: validate-payment-method
    class: App\Flowpipe\Steps\ValidatePaymentMethodStep
    
  - condition:
      field: payment_method
      operator: equals
      value: "credit_card"
    then:
      - type: action
        name: process-credit-card
        class: App\Flowpipe\Steps\ProcessCreditCardStep
    else:
      - condition:
          field: payment_method
          operator: equals
          value: "paypal"
        then:
          - type: action
            name: process-paypal
            class: App\Flowpipe\Steps\ProcessPaypalStep

πŸ“Š Real-World Group Examples

E-commerce Order Validation

# groups/order-validation.yaml
group: order-validation
description: Comprehensive order validation for e-commerce

steps:
  # Customer validation
  - type: action
    name: validate-customer-data
    class: App\Flowpipe\Steps\ValidateCustomerDataStep
    
  # Item validation
  - type: foreach
    name: validate-order-items
    array: items
    steps:
      - type: action
        name: validate-item-data
        class: App\Flowpipe\Steps\ValidateItemDataStep
      - type: action
        name: check-item-availability
        class: App\Flowpipe\Steps\CheckItemAvailabilityStep
        
  # Pricing validation
  - type: action
    name: validate-pricing
    class: App\Flowpipe\Steps\ValidatePricingStep
    
  # Tax calculation
  - type: action
    name: calculate-taxes
    class: App\Flowpipe\Steps\CalculateTaxesStep
    
  # Final total validation
  - type: action
    name: validate-order-total
    class: App\Flowpipe\Steps\ValidateOrderTotalStep

User Onboarding

# groups/user-onboarding.yaml
group: user-onboarding
description: Complete user onboarding process

steps:
  # Account setup
  - type: action
    name: create-user-profile
    class: App\Flowpipe\Steps\CreateUserProfileStep
    
  - type: action
    name: assign-default-role
    class: App\Flowpipe\Steps\AssignDefaultRoleStep
    
  # Preferences setup
  - type: action
    name: setup-user-preferences
    class: App\Flowpipe\Steps\SetupUserPreferencesStep
    
  # Welcome communications
  - type: group
    name: welcome-communications
    config:
      include_tour: true
      send_tips: true
      
  # Analytics tracking
  - type: action
    name: track-registration-event
    class: App\Flowpipe\Steps\TrackRegistrationEventStep

Content Moderation

# groups/content-moderation.yaml
group: content-moderation
description: Multi-stage content moderation process

steps:
  # Automated checks
  - type: action
    name: spam-detection
    class: App\Flowpipe\Steps\SpamDetectionStep
    
  - type: action
    name: profanity-filter
    class: App\Flowpipe\Steps\ProfanityFilterStep
    
  - type: action
    name: image-content-scan
    class: App\Flowpipe\Steps\ImageContentScanStep
    when:
      field: has_images
      operator: equals
      value: true
      
  # AI moderation
  - type: action
    name: ai-content-analysis
    class: App\Flowpipe\Steps\AiContentAnalysisStep
    config:
      confidence_threshold: 0.8
      
  # Human review queue
  - condition:
      field: moderation_score
      operator: less_than
      value: 0.7
    then:
      - type: action
        name: queue-for-human-review
        class: App\Flowpipe\Steps\QueueForHumanReviewStep
    else:
      - type: action
        name: auto-approve-content
        class: App\Flowpipe\Steps\AutoApproveContentStep

πŸ§ͺ Testing Groups

Unit Testing Group Logic

<?php

namespace Tests\Unit\Flowpipe\Groups;

use Tests\TestCase;
use Grazulex\LaravelFlowpipe\Flowpipe;

class UserValidationGroupTest extends TestCase
{
    public function test_user_validation_group_passes_valid_data()
    {
        $result = Flowpipe::fromYaml('groups/user-validation')
            ->send([
                'name' => 'John Doe',
                'email' => '[email protected]',
                'password' => 'SecurePassword123!',
                'terms_accepted' => true,
            ])
            ->execute();

        $this->assertTrue($result->isSuccessful());
    }

    public function test_user_validation_group_fails_invalid_data()
    {
        $result = Flowpipe::fromYaml('groups/user-validation')
            ->send([
                'name' => '',
                'email' => 'invalid-email',
                'password' => '123',
            ])
            ->execute();

        $this->assertFalse($result->isSuccessful());
    }
}

Integration Testing with Groups

<?php

namespace Tests\Feature\Flowpipe;

use Tests\TestCase;
use Grazulex\LaravelFlowpipe\Flowpipe;
use Illuminate\Foundation\Testing\RefreshDatabase;

class UserRegistrationFlowTest extends TestCase
{
    use RefreshDatabase;

    public function test_complete_user_registration_flow()
    {
        $result = Flowpipe::fromYaml('user-registration')
            ->send([
                'name' => 'John Doe',
                'email' => '[email protected]',
                'password' => 'SecurePassword123!',
                'terms_accepted' => true,
            ])
            ->execute();

        $this->assertTrue($result->isSuccessful());
        $this->assertDatabaseHas('users', ['email' => '[email protected]']);
        $this->assertTrue($result->data['welcome_email_sent']);
    }
}

πŸ“ Group Organization Strategies

By Domain

groups/
β”œβ”€β”€ user/
β”‚   β”œβ”€β”€ validation.yaml
β”‚   β”œβ”€β”€ onboarding.yaml
β”‚   └── preferences.yaml
β”œβ”€β”€ order/
β”‚   β”œβ”€β”€ validation.yaml
β”‚   β”œβ”€β”€ processing.yaml
β”‚   └── fulfillment.yaml
└── payment/
    β”œβ”€β”€ validation.yaml
    β”œβ”€β”€ processing.yaml
    └── refund.yaml

By Function

groups/
β”œβ”€β”€ validation/
β”‚   β”œβ”€β”€ user-validation.yaml
β”‚   β”œβ”€β”€ order-validation.yaml
β”‚   └── payment-validation.yaml
β”œβ”€β”€ processing/
β”‚   β”œβ”€β”€ order-processing.yaml
β”‚   β”œβ”€β”€ payment-processing.yaml
β”‚   └── inventory-processing.yaml
└── notifications/
    β”œβ”€β”€ email-notifications.yaml
    β”œβ”€β”€ sms-notifications.yaml
    └── push-notifications.yaml

πŸ’‘ Best Practices

1. Single Responsibility

Each group should have one clear purpose:

# Good: Focused on validation
group: user-validation
description: Validate user input data

# Avoid: Mixed responsibilities  
group: user-validation-and-creation
description: Validate user input and create account

2. Meaningful Names

# Good: Descriptive names
group: payment-processing
group: inventory-management
group: customer-notifications

# Avoid: Generic names
group: group1
group: process-stuff
group: utilities

3. Documentation

group: complex-workflow-group
description: |
  This group handles complex business logic including:
  - Multi-step validation
  - External API calls
  - Data transformation
  - Error recovery
  
  Expected payload structure:
  - customer: object with id, email, name
  - items: array of objects with sku, quantity, price
  
  Returns:
  - validation_status: string
  - processed_items: array
  - total_amount: number

4. Versioning

group: payment-processing
version: "2.1"
description: |
  Version 2.1 changes:
  - Added support for Apple Pay
  - Improved error handling
  - Updated security validations

🎯 What's Next?

πŸš€ Laravel Flowpipe

🏠 Home

🏁 Getting Started

πŸ“š Core Concepts

πŸš€ Advanced Features

πŸ› οΈ Tools & Configuration

πŸ“– Examples


πŸ”— GitHub Repository

Clone this wiki locally