PHP 8.5 Pipe Operator RFC: What It Means for Developers

PHP 8.5 Pipe Operator RFC: What It Means for Developers

There is currently a PHP RFC in voting that seems to make it into PHP 8.5: Pipe Operators. In a third try, the pipe operator will most likely find its way natively to PHP. In this blog post, I want to address the upcoming new operator, the meaning of piping in general and its history and give a final conclusion along with my opinion.

Background: What is Piping and the Pipe Operator

The concept of piping originates from Unix systems, where the pipe symbol (|) is used to pass the output of one command as the input to another, enabling modular and composable workflows.

This idea – originally introduced by Doug McIlroy in the 1960s – laid the foundation for a powerful programming pattern: chaining operations in a readable and linear fashion. In modern programming languages, the pipe operator (|> in many languages) formalizes this pattern, allowing the result of one expression to be directly passed as an argument to the next function. While languages like Elixir, F#, and R have embraced this approach natively, PHP has historically lacked such an operator. Instead, developers simulated piping through method chaining, middleware stacks, or custom pipe() functions.

Pipe Operator Solutions Before PHP 8.5

Even though the RFC is still in voting at the time of writing this blog post, it is very likely that the pipe operator will make it to PHP 8.5, as there are currently more “yes” votes than “no”. In the following, I just assume that PHP 8.5 will implement the pipe operator.

Without the native pipe operator (|>) – meaning: before PHP 8.5 -, it was quite even possible to use the underlying concept of piping – passing data through a series of transformations – in various ways. Though PHP lacked a built-in syntax, functional patterns and middleware pipelines served as effective alternatives across different ecosystems.

Functional Pipe via Closures

In pure PHP, piping is often implemented using higher-order functions. A custom pipe() function allowed chaining operations in a functional style:

PSR-15: Standardized Middleware Pipelines

The PSR-15 standard introduced by PHP-FIG defines MiddlewareInterface and RequestHandlerInterface, enabling interoperable middleware pipelines. For instance, in one of my projects, I use the following middleware:

This middleware is piped at a very early place of the pipe and the application.started value is used at the end to measure how long the request took.

The concept of pipes is used widely in the world of PHP – they are used across frameworks like Symfony (via Symfony HTTP Kernel), Laravel and – as demonstrated – for Laminas/Mezzio to structure linear processing – just like a pipe.

Symfony and Laravel

Both Symfony and Laravel support pipe-like behavior, though implemented differently:

  • In Symfony, middleware-like behavior appears in HttpKernel, Messenger middleware, and EventDispatcher, where listeners or middlewares handle data sequentially.
  • In Laravel, the Pipeline class formalizes functional-style piping. It allows data to be passed through an ordered list of closures or class-based middleware:

But these solutions have also drawbacks.

The most relevant drawback according to the RFC is performance. User-space pipe solutions in PHP suffer from performance overhead due to extra function calls, closures, and internal loops. Some libraries also lead to awkward, nested syntax, especially when conditionals are involved.

In contrast, a native operator removes this overhead, enables compiler optimizations like PFA, and avoids complex constructs like magic methods or middleware stacks. It also improves static analysis, making type compatibility easier to verify.

Pipe Operator RFC for PHP 8.5: What it is and What it means

There were two attempts before, but the current one – Pipe Operator RFC (v3) – proposes the long-anticipated addition to the PHP language: the |> operator. This operator allows the result of an expression on the left to be passed as the first argument to a callable on the right, enabling a clean, functional style of chaining operations. Inspired by similar features in languages like Elixir, F#, this addition aims to make PHP code more readable, solve the above mentioned problems with the current implementations, particularly when performing step-by-step data transformations.

The RFC defines |> as a left-associative binary operator with precedence that ensures it plays nicely with common operations. It supports regular callables, arrow functions, and even partial function application (PFA) when used in combination with PHP’s ... syntax:

This new syntax removes the need for deeply nested function calls or verbose temporary variables. Notably, the RFC excludes support for callables that require pass-by-reference arguments, keeping the operator’s behavior predictable. It also opens the door to future enhancements like native function composition and more powerful static analysis capabilities, since the type flow becomes easier to track across piped operations.

Conclusion

The introduction of the pipe operator in PHP 8.5 represents more than just syntactic sugar – it’s a step toward modernizing the language and embracing functional programming patterns that improve readability, maintainability, and developer experience. While user-space workarounds have existed for years, they came with trade-offs in performance, complexity, and clarity. The native |> operator solves these limitations in a clean, consistent, and efficient way. As PHP continues to evolve, the addition of such features reflects a broader commitment to making the language more expressive and powerful, without losing its pragmatic roots. Whether you’re working with data transformation, functional pipelines, or simply want cleaner code, the pipe operator is a welcome and future-proof addition to every PHP developer’s toolbox.