advanced php language
PHP 8.5 Pipe Operator
The pipe operator |> passes the value on the left into the callable on the right. It is useful when a value moves through several small transformations and you want the code to read from top to bottom.
It does not replace functions, methods, or clear variable names. It gives you another way to express a pipeline when each step is already simple.
The Basic Shape
These two lines do the same thing:
<?php
declare(strict_types=1);
$length = 'Hello World' |> strlen(...);
$sameLength = strlen('Hello World');
echo $length . PHP_EOL;
echo $sameLength . PHP_EOL;
// Prints:
// 11
// 11
The right side must be a callable that accepts the value from the left. First-class callables such as strlen(...), closures, arrow functions, and invokable objects can all be used.
Reading Transformations Left To Right
The pipe operator becomes useful when several transformations happen in sequence.
<?php
declare(strict_types=1);
$title = ' PHP 8.5 Released ';
$slug = $title
|> trim(...)
|> strtolower(...)
|> (fn (string $value): string => str_replace('.', '', $value))
|> (fn (string $value): string => str_replace(' ', '-', $value));
echo $slug . PHP_EOL;
// Prints:
// php-85-released
Without the pipe operator, this would usually become nested function calls or several intermediate variables. Both are valid, but the pipeline makes the order of work obvious.
Adapting Arguments With Closures
Many PHP functions need more than one argument. The pipe operator passes one value, so use a closure when you need to provide the other arguments.
<?php
declare(strict_types=1);
$summary = ' Senior PHP Engineer ';
$result = $summary
|> trim(...)
|> (fn (string $value): string => str_replace('PHP', 'Laravel', $value))
|> (fn (string $value): string => '[' . $value . ']');
echo $result . PHP_EOL;
// Prints:
// [Senior Laravel Engineer]
The closures are not noise here. They show exactly how the piped value is being adapted for functions that need extra context.
Object Methods In A Pipeline
Object methods can be used through first-class callable syntax.
<?php
declare(strict_types=1);
final class TextCleaner
{
public function collapseSpaces(string $value): string
{
return preg_replace('/\s+/', ' ', $value) ?? '';
}
}
$cleaner = new TextCleaner();
$name = " Ada\n Lovelace "
|> trim(...)
|> $cleaner->collapseSpaces(...);
echo $name . PHP_EOL;
// Prints:
// Ada Lovelace
This is useful when a service object owns a small transformation and you want to compose it with other transformations.
When Intermediate Variables Are Better
A pipeline is not automatically clearer. If a step deserves a name, use a variable.
<?php
declare(strict_types=1);
function normaliseEmail(string $email): string
{
return $email
|> trim(...)
|> strtolower(...);
}
$rawEmail = ' ADA@EXAMPLE.COM ';
$normalisedEmail = normaliseEmail($rawEmail);
$domain = substr(strrchr($normalisedEmail, '@') ?: '', 1);
echo $normalisedEmail . PHP_EOL;
echo $domain . PHP_EOL;
// Prints:
// ada@example.com
// example.com
The extracted variable $normalisedEmail makes the later domain parsing easier to understand. Pipelines should remove clutter, not hide meaning.
Avoid Side-Effect Pipelines
The pipe operator works best with transformations that return a value. Be careful with steps that mutate state, write files, send emails, or log as their main purpose.
<?php
declare(strict_types=1);
function trimName(string $name): string
{
return trim($name);
}
function titleCaseName(string $name): string
{
return ucwords(strtolower($name));
}
$displayName = ' ADA LOVELACE '
|> trimName(...)
|> titleCaseName(...);
echo $displayName . PHP_EOL;
// Prints:
// Ada Lovelace
Small pure functions make good pipeline steps because each step is easy to test and review.
What You Should Be Able To Do
After this lesson, you should be able to read and write a simple |> pipeline, use first-class callables and closures on the right side, and decide when a named variable is clearer.
For junior PHP work, this matters because modern codebases often prefer readable data transformations. The professional judgement is knowing when a pipeline improves the code and when it becomes clever for its own sake.
Practice
Practice: Build A Slug Pipeline
Create a small PHP 8.5 example that turns a title into a URL slug using the pipe operator.
Task
Build a pipeline that:
- trims the input title
- lowercases it
- removes apostrophes
- replaces spaces with hyphens
- collapses repeated hyphens
- trims hyphens from the start and end
Use strict types. Put the expected output inside the PHP code block as printed lines or comments.
Afterward, add a short note explaining why some steps use closures instead of first-class callables.
Show solution
This solution uses first-class callables where the existing function already accepts one argument, and closures where the piped value needs extra arguments.
<?php
declare(strict_types=1);
function slugify(string $title): string
{
return $title
|> trim(...)
|> strtolower(...)
|> (fn (string $value): string => str_replace("'", '', $value))
|> (fn (string $value): string => str_replace(' ', '-', $value))
|> (fn (string $value): string => preg_replace('/-+/', '-', $value) ?? '')
|> (fn (string $value): string => trim($value, '-'));
}
echo slugify(" What's New In PHP 8.5 ") . PHP_EOL;
echo slugify(' PHP Pipelines ') . PHP_EOL;
// Prints:
// whats-new-in-php-8.5
// php-pipelines
trim(...) and strtolower(...) can be used directly because they already accept the piped string as their main argument. The str_replace(), preg_replace(), and final trim() steps use closures because they need extra arguments as well as the value coming through the pipeline.