Skip to content

Your First Flow

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

🎯 Your First Flow

← Installation & Setup | Home | Understanding YAML Flows β†’

Let's create your first Laravel Flowpipe workflow! We'll build a simple user registration flow that demonstrates the core concepts.

🎬 Overview

We'll create a user registration workflow that:

  1. Validates user input
  2. Checks email uniqueness
  3. Creates the user account
  4. Sends a welcome email

πŸ“ Step 1: Create the YAML Flow

Create flows/user-registration.yaml:

flow: user-registration
description: Simple user registration workflow

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

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

  - type: action
    name: check-email-uniqueness
    class: App\Flowpipe\Steps\CheckEmailStep
    description: Verify email is not already registered

  - type: action
    name: create-user
    class: App\Flowpipe\Steps\CreateUserStep
    description: Create user account in database

  - type: action
    name: send-welcome-email
    class: App\Flowpipe\Steps\SendWelcomeEmailStep
    description: Send welcome email to new user

πŸ—οΈ Step 2: Create the PHP Step Classes

Create the Steps Directory

mkdir -p app/Flowpipe/Steps

ValidateInputStep.php

<?php

namespace App\Flowpipe\Steps;

use Closure;
use Grazulex\LaravelFlowpipe\Contracts\FlowStep;
use Illuminate\Support\Facades\Validator;
use InvalidArgumentException;

class ValidateInputStep implements FlowStep
{
    public function handle(mixed $payload, Closure $next): mixed
    {
        $validator = Validator::make($payload, [
            'name' => 'required|string|max:255',
            'email' => 'required|email|max:255',
            'password' => 'required|min:8',
            'terms_accepted' => 'required|boolean|accepted',
        ]);

        if ($validator->fails()) {
            throw new InvalidArgumentException(
                'Validation failed: ' . implode(', ', $validator->errors()->all())
            );
        }

        return $next($validator->validated());
    }
}

CheckEmailStep.php

<?php

namespace App\Flowpipe\Steps;

use Closure;
use Grazulex\LaravelFlowpipe\Contracts\FlowStep;
use App\Models\User;
use InvalidArgumentException;

class CheckEmailStep implements FlowStep
{
    public function handle(mixed $payload, Closure $next): mixed
    {
        if (User::where('email', $payload['email'])->exists()) {
            throw new InvalidArgumentException('Email address is already registered');
        }

        return $next($payload);
    }
}

CreateUserStep.php

<?php

namespace App\Flowpipe\Steps;

use Closure;
use Grazulex\LaravelFlowpipe\Contracts\FlowStep;
use App\Models\User;
use Illuminate\Support\Facades\Hash;

class CreateUserStep implements FlowStep
{
    public function handle(mixed $payload, Closure $next): mixed
    {
        $user = User::create([
            'name' => $payload['name'],
            'email' => $payload['email'],
            'password' => Hash::make($payload['password']),
        ]);

        // Add user to payload for next steps
        $payload['user_id'] = $user->id;
        $payload['user'] = $user;

        return $next($payload);
    }
}

SendWelcomeEmailStep.php

<?php

namespace App\Flowpipe\Steps;

use Closure;
use Grazulex\LaravelFlowpipe\Contracts\FlowStep;
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeEmail;

class SendWelcomeEmailStep implements FlowStep
{
    public function handle(mixed $payload, Closure $next): mixed
    {
        Mail::to($payload['user'])->send(new WelcomeEmail($payload['user']));

        $payload['welcome_email_sent'] = true;

        return $next($payload);
    }
}

πŸš€ Step 3: Execute Your Flow

Using Artisan Command

php artisan flowpipe:run user-registration

Using PHP Code

use Grazulex\LaravelFlowpipe\Flowpipe;

// Execute with default data from YAML
$result = Flowpipe::fromYaml('user-registration')->execute();

// Execute with custom data
$result = Flowpipe::fromYaml('user-registration')
    ->send([
        'name' => 'Jane Smith',
        'email' => '[email protected]',
        'password' => 'MySecurePassword456!',
        'terms_accepted' => true,
    ])
    ->execute();

// Check the result
if ($result->isSuccessful()) {
    echo "User registered successfully! ID: " . $result->data['user_id'];
} else {
    echo "Registration failed: " . $result->error->getMessage();
}

Using in a Controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Grazulex\LaravelFlowpipe\Flowpipe;

class RegistrationController extends Controller
{
    public function register(Request $request)
    {
        $result = Flowpipe::fromYaml('user-registration')
            ->send($request->all())
            ->execute();

        if ($result->isSuccessful()) {
            return response()->json([
                'success' => true,
                'user_id' => $result->data['user_id']
            ]);
        }

        return response()->json([
            'success' => false,
            'error' => $result->error->getMessage()
        ], 400);
    }
}

πŸŽ‰ Congratulations!

You've created your first Laravel Flowpipe workflow! Here's what you learned:

  • βœ… YAML Structure: How to define flows declaratively
  • βœ… PHP Steps: Creating step classes that implement FlowStep
  • βœ… Data Flow: How payload moves between steps
  • βœ… Execution: Different ways to run your flows

πŸ” Understanding What Happened

  1. YAML Definition: The flow structure was defined declaratively
  2. Step Execution: Each step received the payload, processed it, and passed it to the next step
  3. Data Transformation: The payload was enriched at each step (validation β†’ email check β†’ user creation β†’ email confirmation)
  4. Error Handling: Any step could throw an exception to stop the flow

🎯 What's Next?

Now that you have a basic flow working, explore these advanced features:

πŸ’‘ Pro Tips

  1. Start Simple: Begin with basic flows and add complexity gradually
  2. Test Steps Individually: Each step should be unit testable
  3. Use Descriptive Names: Make your YAML files self-documenting
  4. Handle Errors: Always consider what could go wrong in each step

πŸš€ Laravel Flowpipe

🏠 Home

🏁 Getting Started

πŸ“š Core Concepts

πŸš€ Advanced Features

πŸ› οΈ Tools & Configuration

πŸ“– Examples


πŸ”— GitHub Repository

Clone this wiki locally