PHP 8.5 Pipe Operator

PHP 8.5 introduced the pipe operator |> for passing a value through a sequence of callables. It reads from left to right: PHP evaluates the expression on the left, sends that value to the callable on the right, and makes the callable's return value available to the next step.

Pipelines can make data transformations easier to follow than deeply nested function calls. They work best when each step accepts one value and returns the value required by the next step.

Pipe Operator Syntax

Place a value or expression on the left and a single-parameter callable on the right.

Syntax:

$result = $value |> $callable;

The right side can be a closure, an arrow function, a first-class callable, or an invokable object. The following expressions are equivalent:

<?php
// Both statements calculate the length of the same string.
$lengthFromPipe = "Hello" |> strlen(...);
$lengthFromCall = strlen("Hello");
?>
Part Role
Left operand Produces the value to transform
|> Passes that value to the next callable
Right operand Receives one argument and returns the next value
Whole expression Evaluates to the callable's return value

Chain Built-in Functions

Use first-class callable syntax with three dots when you want to pipe into a named function. Each stage receives the previous result.

Example:

<?php
$name = "  aisha SHARMA  "
    |> trim(...)       // Remove surrounding spaces.
    |> strtolower(...) // Normalize all letters.
    |> ucwords(...);   // Capitalize each word.

echo $name;
?>

Output:

Aisha Sharma

The pipeline makes the execution order visible. A nested version starts with the outermost function name even though the innermost function runs first.

<?php
// Equivalent result, but the reading order is reversed.
$name = ucwords(strtolower(trim("  aisha SHARMA  ")));
?>

Use a Closure for Extra Arguments

Some functions do not accept the piped value as their only or first argument. Wrap such a call in a closure and place the incoming value where the function expects it.

Example:

<?php
$subtotal = [499, 799, 250]
    |> fn(array $prices): array => array_map(
        fn(int $price): int => $price * 2, // Two items of each product.
        $prices
    )
    |> array_sum(...);

echo "Subtotal: ₹" . $subtotal;
?>

Output:

Subtotal: ₹3096

The closure receives the entire prices array from the pipe. It then supplies the callback as the first argument and the array as the second argument to array_map().

Pipe Through Object Methods

A first-class callable can reference an object method. This is useful when a small service object owns one transformation.

Example:

<?php
final class CurrencyFormatter
{
    public function format(float $amount): string
    {
        // Return a display-ready currency value.
        return "₹" . number_format($amount, 2);
    }
}

$formatter = new CurrencyFormatter();
$label = 1250.5 |> $formatter->format(...);

echo $label;
?>

Output:

₹1,250.50

Use an Invokable Object

An object that defines __invoke() is callable and can appear on the right side of the operator.

<?php
final class AddTax
{
    public function __construct(private float $rate) {}

    public function __invoke(float $amount): float
    {
        // Apply the configured tax rate to one amount.
        return $amount * (1 + $this->rate);
    }
}

$total = 1000 |> new AddTax(0.18);
echo $total;
?>

Output:

1180

Handle Errors in a Pipeline

The pipe operator does not hide exceptions. If a stage throws, later stages do not run. Surround the complete pipeline with normal try and catch handling when failure is expected.

<?php
function decodeJson(string $json): array
{
    // JSON_THROW_ON_ERROR converts invalid JSON into an exception.
    return json_decode($json, true, flags: JSON_THROW_ON_ERROR);
}

try {
    $count = '{"items":[1,2,3]}'
        |> decodeJson(...)
        |> fn(array $data): int => count($data['items']);

    echo "Items: " . $count;
} catch (JsonException $error) {
    echo "Invalid data: " . $error->getMessage();
}
?>

Output:

Items: 3

Common Mistakes

  • Do not write strlen() on the right; that calls the function immediately. Use strlen(...) to create a callable.
  • Make sure each stage accepts exactly the value returned by the previous stage.
  • Use a closure when a function needs additional arguments or expects the piped value in another position.
  • Do not assume the operator changes error handling; exceptions still propagate normally.
  • Do not run this syntax on PHP 8.4 or earlier because it requires PHP 8.5.

Pipe Operator vs Other Styles

Style Best use Trade-off
Pipe operator Several clear one-value transformations Requires PHP 8.5 or later
Temporary variables Debugging or naming important intermediate values Uses more statements
Nested calls One or two short transformations Order becomes harder to read as nesting grows
Method chaining An API designed around one fluent object Requires methods on compatible objects

Tip: Keep temporary variables when their names explain a business step. A pipeline improves reading order, but it should not remove useful meaning.

Conclusion

The PHP 8.5 pipe operator passes a value through callables in left-to-right order. Use first-class callables for simple functions, closures for argument placement, and normal exception handling around risky stages. It is most effective when each transformation is small, focused, and easy to test.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram