Skip to main content

Pipelines: Chaining Multi-Step Logic

Premium
4 min read

Sometimes a Service or Action class grows because it performs multiple sequential steps. For example, when onboarding a new user, you might need to: generate a profile photo, create demo data, activate a trial subscription, and send a welcome email.

You could put all of that in one method, but there's a more structural alternative: Pipelines.

Laravel's Pipeline facade lets you send data through a series of "pipe" classes, each performing one step. It's the same mechanism Laravel uses internally for middleware.

Pipelines are not a replacement for Services or Actions. They're an alternative for multi-step sequential operations where each step is its own class.


How Pipelines Work

The basic Pipeline syntax:

use Illuminate\Support\Facades\Pipeline;
 
$user = Pipeline::send($user)
->through([
GenerateProfilePhoto::class,
CreateDemoProject::class,
ActivateTrialSubscription::class,
SendWelcomeEmail::class,
])
->thenReturn();

Each "pipe" class receives the data, does its work, and passes it to the next pipe. Here's what one looks like:

app/Pipes/GenerateProfilePhoto.php:

namespace App\Pipes;
 
use App\Models\User;
use Closure;
 
class GenerateProfilePhoto
{
public function handle(User $user, Closure $next)
{
$user->update([
'avatar' => 'https://ui-avatars.com/api/?name=' . urlencode($user->name),
]);
 
return $next($user);
}
}

app/Pipes/CreateDemoProject.php:

namespace App\Pipes;
 
use App\Models\User;
use App\Models\Project;
use Closure;
 
class CreateDemoProject
{
public function handle(User $user, Closure $next)
{
Project::create([
'user_id' => $user->id,
'name' => 'Demo project 1',
]);
 
return $next($user);
}
}

The pattern is always the same: accept the data, do your work, call $next($data).


Using Pipelines in the Controller

In the Controller, you would replace a long Service method with...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (36 h 00 min)

You also get:

60 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

DS
Dmytro Sakharuk ✓ Link copied!

It should be noted that the pipe operator was introduced in PHP 8.5.

use App\Models\User;
 
class Pipe1
{
public function __invoke(User $user): User
{
$user->name .= ' suffix 1';
 
return $user;
}
}
 
class Pipe2
{
public function __invoke(User $user): User
{
$user->name .= ' suffix 2';
 
return $user;
}
}
 
$user = auth()->user()
|> new Pipe1
|> new Pipe2;
 
dd($user->name); // Username suffix 1 suffix 2

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.