| alcaeus | Abstain | 2026-07-31 09:28 |
| alexandredaubois | Abstain | 2026-07-29 06:54 |
| as | No | 2026-08-08 03:47 |
| beberlei | No | 2026-07-28 07:16 |
| bmajdak | Yes | 2026-08-05 22:34 |
| brzuchal | No | 2026-07-29 05:06 |
| crell | No | 2026-07-28 15:44 |
| cschneid | No | 2026-07-28 16:47 |
| daniels | Abstain | 2026-08-10 14:34 |
| derick | Abstain | 2026-07-31 09:45 |
| dharman | Yes | 2026-07-29 13:29 |
| duncan3dc | No | 2026-07-28 09:11 |
| galvao | Yes | 2026-07-28 06:24 |
| iliaa | Yes | 2026-07-28 12:46 |
| imsop | Yes | 2026-07-29 12:44 |
| jbnahan | Abstain | 2026-08-04 08:06 |
| jordikroon | No | 2026-07-28 16:53 |
| kalle | No | 2026-07-30 11:15 |
| kguest | No | 2026-08-05 14:51 |
| lstrojny | Yes | 2026-07-29 06:10 |
| mbeccati | Yes | 2026-07-28 07:46 |
| mcmic | No | 2026-07-28 15:39 |
| ocramius | No | 2026-07-28 04:27 |
| pajoye | Yes | 2026-07-30 01:59 |
| ramsey | Yes | 2026-07-29 01:29 |
| sebastian | Abstain | 2026-07-28 04:39 |
| sergey | Yes | 2026-08-02 18:56 |
| shivam | No | 2026-07-31 14:16 |
| thekid | Yes | 2026-08-08 08:33 |
| theodorejb | Yes | 2026-08-04 12:14 |
| timwolla | Yes | 2026-07-28 06:01 |
| trowski | Yes | 2026-07-30 16:41 |
| weilindu | Abstain | 2026-07-28 16:01 |
Copied from wiki.php.net, last synchronized Oct 13, 2026 11:52 UTC
PHP 8.5 introduced the pipe operator (|>), enabling functional-style transformation chains. A common pattern is piping a variable through transformations and assigning the result back to the same variable. This RFC proposes |>=, a compound assignment form that eliminates the repetition, consistent with PHP's existing compound assignment operators (+= , .=, ??=, etc.):
// Before
$this->requestData = array_filter($this->requestData);
// or
$this->requestData = $this->requestData |> array_filter(...);
$headers = $headers
|> array_change_key_case(?, CASE_LOWER)
|> array_filter(?, fn($v) => $v !== '');
// After
$this->requestData |>= array_filter(...);
$headers |>= array_change_key_case(?, CASE_LOWER)
|> array_filter(?, fn($v) => $v !== '');
The expression $x |>= callable is equivalent to $x = $x |> callable.
When the right-hand side contains a pipe chain, the variable is spliced into the leftmost position:
$x |>= fn1(...) |> fn2(...) |> fn3(...);
// Equivalent to:
$x = $x |> fn1(...) |> fn2(...) |> fn3(...);
This works because |> has higher precedence than |>=. The parser groups the RHS as a pipe chain, and the compiler flattens it, inserting the LHS variable as the initial input.
All variable types that support compound assignment are supported:
$x |>= strtoupper(...); // Simple variable
$data["key"] |>= strtoupper(...); // Array dimension
$obj->name |>= strtoupper(...); // Object property
Foo::$value |>= strtoupper(...); // Static property
All callable styles supported by |> work with |>= (including PFA, which eliminates the need for closure wrappers):
$x |>= strtoupper(...); // First-class callable
$x |>= Formatter::normalize(...); // Static method
$x |>= $formatter->normalize(...); // Instance method
$x |>= (fn($v) => $v * 2); // Arrow function (must be parenthesized)
$x |>= $storedCallable; // Stored callable
$x |>= str_replace('a', 'b', ?); // Partial function application
Like other compound assignment operators, |>= produces the assigned value as its expression result:
$x = 5;
$y = ($x |>= (fn($v) => $v * 3));
// $x === 15, $y === 15
When the LHS contains sub-expressions, they are evaluated exactly once:
$arr[expensive_call()] |>= strtoupper(...);
// expensive_call() is invoked only once
With the manual $x = $x |> ... pattern, sub-expressions are evaluated twice: once on each side of the assignment. |>= is both more correct and more performant. This is the same guarantee that ??= provides over $x = $x ?? default, implemented using the same compile-time memoization mechanism.
Note: for chained property access like $a->b->c |>= strtoupper(...), intermediate fetches (e.g. $a->b) are evaluated once for the read and once for the write-back. This is consistent with ??= and all other compound assignment operators.
|>= has the same precedence and associativity as all other assignment operators (=, += , .=, ??=, etc.): right-associative, binding tighter than the keyword operators (and, or, xor, yield, print, etc.) but looser than all other operators.
Because |> binds tighter than |>=, pipe chains on the RHS are grouped first. The compiler then splices the LHS variable into the chain. For example:
$foo |>= bar(...) |> baz(...);
// is interpreted as:
$foo = (($foo |> bar(...)) |> baz(...));
Right-associativity with other assignment operators:
// Nested |>=: right-to-left evaluation
$foo |>= $bar |>= double(...);
// is interpreted as:
$foo |>= ($bar |>= double(...));
// 1. $bar = double($bar), expression result is the new $bar
// 2. $foo = ($foo |> new_$bar), i.e., new_$bar is used as the callable
// Mixed with other compound assignments
$foo += $bar |>= triple(...);
// is interpreted as:
$foo += ($bar |>= triple(...));
// 1. $bar = triple($bar), expression result is the new $bar
// 2. $foo += new_$bar
// |>= result used with another operator
$result = $x |>= double(...) or die('failed');
// is interpreted as:
($result = ($x |>= double(...))) or die('failed');
// because `or` has lower precedence than assignment
Consistent with |>:
$x |>= fn($v) => $v * 2; // Fatal error: must be parenthesized
$this |>= trim(...); // Fatal error: Cannot re-assign $this
getVal() |>= strtoupper(...); // Fatal error: Can't use function return value in write context
$x |>= sort(...); // Error: Argument #1 could not be passed by reference
// Before
$input = trim($input) |> strtolower(...);
// After
$input |>= trim(...) |> strtolower(...);
When transformations are conditional, sequential |>= reads naturally:
// Before
$this->user->displayName = trim($this->user->displayName);
if ($normalize) {
$this->user->displayName = strtolower($this->user->displayName);
}
$this->user->displayName = ucfirst($this->user->displayName);
// After
$this->user->displayName |>= trim(...);
if ($normalize) {
$this->user->displayName |>= strtolower(...);
}
$this->user->displayName |>= ucfirst(...);
The value of |>= scales with variable complexity:
// Before
$this->currentOrder->lineItems = array_unique($this->currentOrder->lineItems) |> array_values(...)
// After
$this->currentOrder->lineItems |>= array_unique(...) |> array_values(...);
None. The token |>= is currently a syntax error in all PHP versions.
Next PHP 8.x (8.6).
IDEs and static analyzers that support |> would need to add support for |>=. The semantics are identical to $x = $x |> ..., so type inference requires no new logic.
The tokenizer extension gains a new T_PIPE_EQUAL constant. No other extensions are affected.
No impact.
None.
|> (e.g., new callable styles) would automatically apply to |>= since they share the same callable dispatch logic in the compiler.|>= has a dedicated AST node, the compiler knows at compile time that the variable is read and immediately overwritten. The Implicit Move Optimisation RFC proposes an opcache optimization for exactly this $x = func($x) pattern, avoiding unnecessary copy-on-write copies. |>= would benefit from that optimization automatically, and could potentially emit the implicit-move flag directly at compile time without requiring opcache's SSA analysis (an optimization the manual $x = $x |> ... form cannot support).This RFC requires a 2/3 majority to pass.
Vote: Implement the pipe assignment operator as outlined in the RFC? — Yes: 14 · No: 12 · Abstain: 7 (closed)
Implementation: https://github.com/php/php-src/pull/22633
After the RFC is implemented, this section will contain:
|>= the same precedence as |> was considered, but $x |>= fn1(...) |> fn2(...) would parse as ($x |>= fn1(...)) |> fn2(...), where only fn1's result is assigned and fn2's result is discarded. Assignment-level precedence with compile-time chain flattening produces the expected behavior.