-
-
Notifications
You must be signed in to change notification settings - Fork 0
Your First Flow
Jean-Marc Strauven edited this page Aug 6, 2025
·
1 revision
β 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.
We'll create a user registration workflow that:
- Validates user input
- Checks email uniqueness
- Creates the user account
- Sends a welcome email
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
mkdir -p app/Flowpipe/Steps
<?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());
}
}
<?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);
}
}
<?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);
}
}
<?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);
}
}
php artisan flowpipe:run user-registration
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();
}
<?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);
}
}
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
- YAML Definition: The flow structure was defined declaratively
- Step Execution: Each step received the payload, processed it, and passed it to the next step
- Data Transformation: The payload was enriched at each step (validation β email check β user creation β email confirmation)
- Error Handling: Any step could throw an exception to stop the flow
Now that you have a basic flow working, explore these advanced features:
- Understanding YAML Flows - Learn all YAML features
- Step Groups - Organize and reuse step collections
- Error Handling - Add retry logic and fallbacks
- Conditions & Branching - Create dynamic workflows
- Start Simple: Begin with basic flows and add complexity gradually
- Test Steps Individually: Each step should be unit testable
- Use Descriptive Names: Make your YAML files self-documenting
- Handle Errors: Always consider what could go wrong in each step
Laravel Flowpipe - YAML-driven workflow engine for Laravel
GitHub: Laravel Flowpipe Repository | Support: GitHub Issues
Quick Navigation: Home β’ Installation β’ Configuration β’ Commands β’ Examples
π§ Developed by Grazulex