How to build sequences with Laravel pipelines

By Luis Güette

Recently, the Laravel team added a section in the documentation about pipelines, and I think it is a good opportunity to talk about pipelines and how useful they are.

But first, what are pipelines?

Pipelines are a design pattern that enables the creation and execution of a sequence of operations. Much like an assembly line, where each step prepares a product for the next station along the line, pipelines are a group of functions linked together, so the output of the preceding function serves as the input of the following function. Laravel employs this pattern internally, such as in middleware.

How do pipelines work?

There is a Pipeline facade which provides a couple of useful methods to pipe a given input through a series of invokable classes or closures. Here is an example:

use App\Models\User;
use Illuminate\Support\Facades\Pipeline;
 
$user = User::create([...]);
 
$user = Pipeline::send($user)
->through([
SendWelcomeEmail::class,
SubscribeToNewsletter::class,
GenerateAvatar::class,
])
->then(fn (User $user) => $user);
  • We use send($user) method to inject the initial data. In this case, the new created user.

  • The through([...]) method to provide the operations we want to execute with the input we are giving.

  • Finally, the then() runs the pipeline and returns the result.

For each invokable class, two parameters are received: the input and the $next closure. Here is an example:

use Closure;
use App\Models\User;
 
class SendWelcomeEmail
{
public function handle(User $user, Closure $next)
{
$user->notify(new InvoicePaid($invoice));
 
$next($user);
}
}


When you invoke the $next closure, the next invokable class in the pipeline will be invoked. Additionally, there other useful methods you can use to setup the pipeline:

  • The pipe($pipes) method enables you to add extra pipes into the pipeline. For example:

use App\Models\User;
use Illuminate\Support\Facades\Pipeline;
 
$user = User::create([...]);
 
$pipeline = Pipeline::send($user)
->through([
GenerateAvatar::class,
]);
 
if (! $user->isAdmin) {
$pipeline->pipe([
SendWelcomeEmail::class,
SubscribeToNewsletter::class,
]);
}
 
$user = $pipeline->then(fn (User $user) => $user);
  • The via($method) method allows you to set the method to call on the pipes. By default, it is set to handle.

  • The thenReturn() method runs the pipeline and automatically returns the result:

// Instead of using then()
$user = Pipeline::send($user)
->through([...])
->then(fn (User $user) => $user);
 
// You can use thenReturn()
$user = Pipeline::send($user)
->through([...])
->thenReturn();
  • The setContainer() method enables you to set the container instance, this can be useful if you want to manually instantiate the Pipeline class, for instance:

// Using the setContainer() method
(new Pipeline)
->setContainer(app())
 
// But, you can also pass the container instance in the class constructor
(new Pipeline(app()))


Laravel pipelines are a powerful tool that allows developers to easily build and execute a sequence of operations in a clean and organized way. They are flexible and can be customized to fit any use case, making them a valuable addition to any Laravel project. By leveraging the pipeline pattern, developers can improve the scalability and maintainability of their code while also making it easier to implement complex and multi-step processes.

Laravel’s documentation on pipelines: https://laravel.com/docs/10.x/helpers#pipeline

Luis Güette
Software Developer
Author Image

Interested in speaking with a developer?

Connect with us.
©2024 Kirschbaum Development Group LLC Privacy Policy Terms of Service