[RFC] Pipe Assignment Operator

php.internals

Caleb White

53 days ago
Hi internals, I'd like to open discussion on my (first!) RFC for the pipe assignment operator (|>=): https://wiki.php.net/rfc/pipe_assignment_operator It adds a compound assignment form of the pipe operator, so that $x |>= callable is shorthand for $x = $x |> callable, with support for chaining. Implementation with tests is at: https://github.com/php/php-src/pull/22633 Looking forward to your feedback. Thanks! Caleb

Tim Düsterhus

50 days ago
Hi On 2026-07-10 06:45, Caleb White wrote:
> I'd like to open discussion on my (first!) RFC for the pipe assignment > operator (|>=): > https://wiki.php.net/rfc/pipe_assignment_operator > > It adds a compound assignment form of the pipe operator, so that > $x |>= callable is shorthand for $x = $x |> callable, with > support for chaining. Implementation with tests is at: > https://github.com/php/php-src/pull/22633
Quick note regarding formalities: The voting widget was missing the “Abstain” option, which I just added for you. I haven't yet looked at the RFC contents. Best regards Tim Düsterhus

Caleb White

50 days ago
On Monday, July 13th, 2026 at 09:11, Tim Düsterhus <tim@bastelstu.be> wrote:
> Quick note regarding formalities: The voting widget was missing the > “Abstain” option, which I just added for you.
Ah thanks! I just modified the template though, so that probably needs to be updated as well. Caleb

Tim Düsterhus

50 days ago
Hi On 2026-07-13 16:24, Caleb White wrote:
> Ah thanks! I just modified the template though, so that probably needs > to be updated as well.
It's already in the template at https://wiki.php.net/rfc/template#voting_choices (since 2025-08-31, when the “Abstain” RFC passed). Unsure what happened, the rest of your RFC seems to match the current version of the template, particularly the “RFC Impact” section which also got recent updates. Best regards Tim Düsterhus

Caleb White

50 days ago
On Monday, July 13th, 2026 at 09:34, Tim Düsterhus <tim@bastelstu.be> wrote:
> It's already in the template at > https://wiki.php.net/rfc/template#voting_choices (since 2025-08-31, when > the “Abstain” RFC passed). Unsure what happened, the rest of your RFC > seems to match the current version of the template, particularly the > “RFC Impact” section which also got recent updates.
Hmm, not sure---could have accidentally deleted the line in Neovim prior to copy/pasting. Thanks again for catching that! Best, Caleb

mickmackusa

50 days ago
Ooooh, fun. Can we informally call |>= the "volcano operator" (like ?: is the Elvis operator)? ...if only Hershey's Kisses had two paper strips coming out of the top. mickmackusa

Ben Ramsey

50 days ago
On 7/13/26 09:45, mickmackusa wrote:
> Ooooh, fun. Can we informally call |>= the "volcano operator" (like ?: is > the Elvis operator)? > > ...if only Hershey's Kisses had two paper strips coming out of the top. > > mickmackusa >
I like to think of |> as the volcano operator, while |>= is the erupting volcano operator. ;-) Cheers, Ben

Holly Schilling

50 days ago
I won’t get to vote on this RFC, but I wanted to give my brief opinion. To be fair, my initial opinion was that I loved the symmetry of this along with `+=`, `-=`, and similar operators, but really hated how I assumed it was likely be used. I started typing up a message showing examples of how it could be used, but as I did I fell in love with it. It’s a little annoying to type on the standard US Keyboard layout, but its readable as a syntax and has a clear meaning once understood. This is the example that made me really love the <<Exploding Volcano>> operator (with PFA): ``` $array |>= array_map(transform(…), …); ``` Holly

Tim Düsterhus

50 days ago
Hi On 2026-07-10 06:45, Caleb White wrote:
> I'd like to open discussion on my (first!) RFC for the pipe assignment > operator (|>=): > https://wiki.php.net/rfc/pipe_assignment_operator
I've given the RFC a read now and have the following comments: 1. Conceptionally I like the idea of having an “in-place modification operator” for function calls and the semantics of the operator seem to be consistent with the existing “modify-assign” operators we have, particularly also with regard to operand order. Nice idea! 2. I appreciate how detailed the RFC describes that the feature will just “work as expected” (e.g. with regard to variables targets or callable styles), this is good to avoid any ambiguity. 3. The only thing I'm missing for the semantics is an explicit explanation of the operator precedence and associativity (it has the same precedence and associativity as any other assignment operator; but this needs to be in the RFC). And please also include explicit examples along the lines of: If you write `$foo |>= bar(...) |> baz(...)` it will be interpreted as if you have written `$foo = (($foo |> bar(...)) |> baz(...))` with the very explicit redundant parentheses. Please also include some additional more complex examples, e.g. `$foo |>= $bar |>= …`, `$foo += $bar |>= …` and similar to make sure there is no ambiguity for possible use cases that users might have. 4. For the examples, I'd like to note that some of the “before” examples are needlessly complex and might not fairly represent the old code. Specifically: $input = $input |> trim(...) |> strtolower(...); $this->currentOrder->lineItems = $this->currentOrder->lineItems |> array_unique(...) |> array_values(...) |> array_reverse(...); could already be: $input = trim($input) |> strtolower(...); $this->currentOrder->lineItems = array_unique($this->currentOrder->lineItems) |> array_values(...) |> array_reverse(...); Best regards Tim Düsterhus

Caleb White

49 days ago
On Monday, July 13th, 2026 at 12:23, Tim Düsterhus <tim@bastelstu.be> wrote:
> 1. > > Conceptionally I like the idea of having an “in-place modification > operator” for function calls and the semantics of the operator seem to > be consistent with the existing “modify-assign” operators we have, > particularly also with regard to operand order. Nice idea!
Thanks! I'm glad others think so as well :).
> 2. > > I appreciate how detailed the RFC describes that the feature will just > “work as expected” (e.g. with regard to variables targets or callable > styles), this is good to avoid any ambiguity.
Thanks again, trying to make it as clear as possible.
> 3. > > The only thing I'm missing for the semantics is an explicit explanation > of the operator precedence and associativity (it has the same precedence > and associativity as any other assignment operator; but this needs to be > in the RFC). And please also include explicit examples along the lines > of: > > If you write `$foo |>= bar(...) |> baz(...)` it will be interpreted as > if you have written `$foo = (($foo |> bar(...)) |> baz(...))` with the > very explicit redundant parentheses. > > Please also include some additional more complex examples, e.g. `$foo > |>= $bar |>= …`, `$foo += $bar |>= …` and similar to make sure there is > no ambiguity for possible use cases that users might have.
I've added a section in the RFC for this and included more complex examples.
> 4. > > For the examples, I'd like to note that some of the “before” examples > are needlessly complex and might not fairly represent the old code. > Specifically: > > $input = $input |> trim(...) |> strtolower(...); > $this->currentOrder->lineItems = $this->currentOrder->lineItems > |> array_unique(...) > |> array_values(...) > |> array_reverse(...); > > could already be: > > $input = trim($input) |> strtolower(...); > $this->currentOrder->lineItems = > array_unique($this->currentOrder->lineItems) > |> array_values(...) > |> array_reverse(...);
I've cleaned up the examples to make them more representative of existing code. Best, Caleb

Tim Düsterhus

49 days ago
Hi On 2026-07-13 21:02, Caleb White wrote:
>> The only thing I'm missing for the semantics is an explicit >> explanation >> of the operator precedence and associativity (it has the same >> precedence >> and associativity as any other assignment operator; but this needs to >> be >> in the RFC). And please also include explicit examples along the lines >> of: >> >> If you write `$foo |>= bar(...) |> baz(...)` it will be interpreted as >> if you have written `$foo = (($foo |> bar(...)) |> baz(...))` with the >> very explicit redundant parentheses. >> >> Please also include some additional more complex examples, e.g. `$foo >> |>= $bar |>= …`, `$foo += $bar |>= …` and similar to make sure there >> is >> no ambiguity for possible use cases that users might have. > > I've added a section in the RFC for this and included more complex > examples.
Thank you. One note regarding “the lowest precedence level, right-associative”. This is not quite correct. While the assignment operators have fairly low precedence, they are not the lowest. As an example, the infamous `$foo = bar() or die()` pattern relies on `or` having a lower precedence than assignment. This should be corrected. The `$result = ($x |>= double(...)) |> triple(...);` example also doesn't showcase precedence, because of the explicit parentheses. ------ Looking at the RFC examples again, I was reminded of this RFC: https://wiki.php.net/rfc/implicit_move_optimisation, which concerns itself with optimizing the `$foo = func($foo);` case. Perhaps it makes sense to list this in the references section, because with `|>=` this “in-place” reassignment would become an official pattern. Best regards Tim Düsterhus

Caleb White

49 days ago
On Tuesday, July 14th, 2026 at 03:22, Tim Düsterhus <tim@bastelstu.be> wrote:
> Thank you. One note regarding “the lowest precedence level, > right-associative”. This is not quite correct. While the assignment > operators have fairly low precedence, they are not the lowest. As an > example, the infamous `$foo = bar() or die()` pattern relies on `or` > having a lower precedence than assignment. This should be corrected. > > The `$result = ($x |>= double(...)) |> triple(...);` example also > doesn't showcase precedence, because of the explicit parentheses.
Ah, yes. I meant among the symbolic operators but you are correct and I've updated to make this more clear. I removed the explicit parentheses from the example.
> Looking at the RFC examples again, I was reminded of this RFC: > https://wiki.php.net/rfc/implicit_move_optimisation, which concerns > itself with optimizing the `$foo = func($foo);` case. Perhaps it makes > sense to list this in the references section, because with `|>=` this > “in-place” reassignment would become an official pattern.
I've added this to the references and discussed it in the Future Scope section. Best, Caleb

Tim Düsterhus

44 days ago
Hi On 7/14/26 13:37, Caleb White wrote:
> On Tuesday, July 14th, 2026 at 03:22, Tim Düsterhus <tim@bastelstu.be> wrote: >> Thank you. One note regarding “the lowest precedence level, >> right-associative”. This is not quite correct. While the assignment >> operators have fairly low precedence, they are not the lowest. As an >> example, the infamous `$foo = bar() or die()` pattern relies on `or` >> having a lower precedence than assignment. This should be corrected. >> >> The `$result = ($x |>= double(...)) |> triple(...);` example also >> doesn't showcase precedence, because of the explicit parentheses. > > Ah, yes. I meant among the symbolic operators but you are correct and I've > updated to make this more clear. I removed the explicit parentheses from the > example.
Thank you, the precedence section LGTM now. And overall I don't have any further comments regarding the contents of the RFC. Best regards Tim Düsterhus

Caleb White

43 days ago
On Sunday, July 19th, 2026 at 07:40, Tim Düsterhus <tim@bastelstu.be> wrote:
> Thank you, the precedence section LGTM now. And overall I don't have any > further comments regarding the contents of the RFC. > > Best regards > Tim Düsterhus
Awesome! Thank you sir for all your feedback and help! Best, Caleb

Larry Garfield

47 days ago
On Thu, Jul 9, 2026, at 11:45 PM, Caleb White wrote:
> Hi internals, > > I'd like to open discussion on my (first!) RFC for the pipe assignment > operator (|>=): > https://wiki.php.net/rfc/pipe_assignment_operator > > It adds a compound assignment form of the pipe operator, so that > $x |>= callable is shorthand for $x = $x |> callable, with > support for chaining. Implementation with tests is at: > https://github.com/php/php-src/pull/22633 > > Looking forward to your feedback. > > Thanks! > Caleb
Perhaps weirdly, I am not a huge fan of this RFC. I'm open to pipe-compound operators (the other that's been suggested is a null-safe ?|>, which I'd support), but I'm not sure of the use case for this one. That may be because, from a functional programming point of view, piping a back to itself makes little if any sense. Values should be immutable, so you would be doing $b = $a |> foo(...) |> bar(...) |> baz(...); I cannot think of a case where I would want to put $a on the left side, too. How realistic is this use case? I don't think this RFC would cause any harm, I suppose, so I probably won't vote against it. But at the moment I don't see a compelling reason to vote for it. A concrete real-world use case would help make that case, because I cannot come up with one myself. --Larry Garfield

Nick

47 days ago
On 16.07.26 04:07, Larry Garfield wrote:
> On Thu, Jul 9, 2026, at 11:45 PM, Caleb White wrote: >> Hi internals, >> >> I'd like to open discussion on my (first!) RFC for the pipe assignment >> operator (|>=): >> https://wiki.php.net/rfc/pipe_assignment_operator >> >> It adds a compound assignment form of the pipe operator, so that >> $x |>= callable is shorthand for $x = $x |> callable, with >> support for chaining. Implementation with tests is at: >> https://github.com/php/php-src/pull/22633 >> >> Looking forward to your feedback. >> >> Thanks! >> Caleb > Perhaps weirdly, I am not a huge fan of this RFC. I'm open to pipe-compound operators (the other that's been suggested is a null-safe ?|>, which I'd support), but I'm not sure of the use case for this one. > > That may be because, from a functional programming point of view, piping a back to itself makes little if any sense. Values should be immutable, so you would be doing > > $b = $a |> foo(...) |> bar(...) |> baz(...); > > I cannot think of a case where I would want to put $a on the left side, too. How realistic is this use case? > > I don't think this RFC would cause any harm, I suppose, so I probably won't vote against it. But at the moment I don't see a compelling reason to vote for it. A concrete real-world use case would help make that case, because I cannot come up with one myself. > > --Larry Garfield
Hey Larry, // before public function makeSlug(string $value): string {     $value = $value |> mb_strtolower(...); // ...     $number = $this->getNextSlugNumber($value); // checks DB     if (0 < $number) {  $value .= "-$number";  }     return $value; } // after public function makeSlug(string $value): string {     $value |>= mb_strtolower(...) ; // ...     $number = $this->getNextSlugNumber($value); // checks DB     if (0 < $number) {  $value .= "-$number"; }     return $value; } Currently we have to make assignment gymnastics even for use cases that do not require an immutable second value. Would argue many people in PHP do and will use pipes for readability, not because they suddenly write PHP from a functional programming point of view. This is a good proposal, IMO.
-- Cheers Nick

Alexandru Pătrănescu

47 days ago
Hi Nick, On Thu, 16 Jul 2026, 01:30 Nick Sdot, <php@nicksdot.dev> wrote:
> > > // before > public function makeSlug(string $value): string { > $value = $value |> mb_strtolower(...); // ... > $number = $this->getNextSlugNumber($value); // checks DB > if (0 < $number) { $value .= "-$number"; } > return $value; > } > > // after > public function makeSlug(string $value): string { > $value |>= mb_strtolower(...) ; // ... > $number = $this->getNextSlugNumber($value); // checks DB > if (0 < $number) { $value .= "-$number"; } > return $value; > } > > > Currently we have to make assignment gymnastics even for use cases that > do not require an immutable second value. Would argue many people in PHP > do and will use pipes for readability, not because they suddenly write > PHP from a functional programming point of view. This is a good > proposal, IMO. > >
I would argue that is a very bad practice in php, to alter the actual function parameter variable. That is because any stack trace obtained will not reflect the initial value but the modified value. And generally, it is a bad practice to override a variable with some other value that represents something different. You could have had incrementally: $lowercaseValue, and $slug/$valueWithSlugNumber.
-- Alex

Holly Schilling

46 days ago
> I would argue that is a very bad practice in php, to alter the actual function parameter variable. That is because any stack trace obtained will not reflect the initial value but the modified value. > > And generally, it is a bad practice to override a variable with some other value that represents something different. You could have had incrementally: $lowercaseValue, and $slug/$valueWithSlugNumber.
While I agree, we need to accept that often people do not use the best practices when coding. PHP makes the barrier to entry low, which invites people who are still learning what best practices are. I wanted to argue against this for exactly this reason, but it’s really not that bad. When combined with FCC, PFA, and pipe chaining, it can really condense code. My only hesitation is that what we’re going to end up with is a lot of: ``` $foo |>= a(…) $foo |>= b(…) $foo |>= c(…) ``` This completely defeats the spirit of this operation (and probably has terrible performance). Holly

Caleb White

45 days ago
Hi everyone, thanks for the feedback. On Friday, July 17th, 2026 at 13:08, Larry Garfield <larry@garfieldtech.com> wrote:
> Perhaps weirdly, I am not a huge fan of this RFC. I'm open to pipe-compound operators (the > other that's been suggested is a null-safe ?|>, which I'd support), but I'm not sure of the > use case for this one. > > That may be because, from a functional programming point of view, piping a back to itself makes > little if any sense. Values should be immutable, so you would be doing > > $b = $a |> foo(...) |> bar(...) |> baz(...); > > I cannot think of a case where I would want to put $a on the left side, too. How realistic is this > use case? > > I don't think this RFC would cause any harm, I suppose, so I probably won't vote against > it. But at the moment I don't see a compelling reason to vote for it. A concrete real-world > use case would help make that case, because I cannot come up with one myself. > > --Larry Garfield
I understand the FP perspective, but PHP isn't an immutable language. We mutate variables constantly; that's why `+=`, `.=`, and `??=` exist. The motivation for this RFC came from seeing this pattern and wishing that such an operator existed. Here are patterns from a production codebase: Property self-assignment with filter + reindex: // before: $this->personnel repeated $this->personnel = array_values(array_filter( $this->personnel, fn ($u) => ($u['id'] ?? null) !== $userId, )); // after: appears once $this->personnel |>= array_filter(?, fn ($u) => ($u['id'] ?? null) !== $userId) |> array_values(...); Here's another common Laravel pattern (real example from codebase), wrapping a variable in `collect()` to transform it, then converting back with `->all()`: $filters = collect($filters) ->map(function ($value) { // logic... }) ->all(); At its core this is just `$filters = transform($filters)`. People already reach for this self-assignment pattern constantly; collections just provide the fluent API for the transformation. With `|>=` and native array functions you get the same fluency without the round-trip: $filters |>= some_transform(...); Even simple `$x = func($x)` calls benefit; the variable doesn't need to be duplicated on both sides: // all real patterns from one codebase $post_data = json_decode($post_data, true); $dates = array_reverse($dates); $model = ltrim($model, '\\/'); $items = array_slice($items, $offset, $per_page); $formData['search']['name'] = str_replace('\\', '', $formData['search']['name']); // become $post_data |>= json_decode(?, true); $dates |>= array_reverse(...); $model |>= ltrim(?, '\\/'); $items |>= array_slice(?, $offset, $per_page); $formData['search']['name'] |>= str_replace('\\', '', ?); Here's another production example (not the nicest code but you get the point), it's much cleaner using `|>=` than repeating the expression: // before $params['current']['pallet_quantity'] = intval($params['current']['pallet_quantity']); $params['current']['pallet_cost'] = floatval($params['current']['pallet_cost']); $params['current']['box_quantity'] = intval($params['current']['box_quantity']); $params['current']['cox_cost'] = floatval($params['current']['box_cost']); $params['current']['cogs'] = floatval($params['current']['cogs']); // after $params['current']['pallet_quantity'] |>= intval(...); $params['current']['pallet_cost'] |>= floatval(...); $params['current']['box_quantity'] |>= intval(...); $params['current']['cox_cost'] |>= floatval(...); $params['current']['cogs'] |>= floatval(...); This is the same argument as `.=`; nobody writes `$x = $x . ' suffix'` anymore. The benefit scales with variable complexity. Sequential transforms in business logic also clean up nicely with PFA: // from real codebase $model = ltrim($model, '\\/'); $model = str_replace('/', '\\', $model); // becomes a single expression $model |>= ltrim(?, '\\/') |> str_replace('/', '\\', ?); The consistency argument is also worth noting. Every binary operator where in-place transformation makes sense has a compound assignment form. We accepted `|>` as a first-class operator; its compound form follows the same pattern as `+=`, `.=`, `??=`, etc. On Friday, July 17th, 2026 at 13:08, Nick Sdot <php@nicksdot.dev> wrote:
> Hey Larry, > > // before > public function makeSlug(string $value): string { > $value = $value |> mb_strtolower(...); // ... > $number = $this->getNextSlugNumber($value); // checks DB > if (0 < $number) { $value .= "-$number"; } > return $value; > } > > // after > public function makeSlug(string $value): string { > $value |>= mb_strtolower(...) ; // ... > $number = $this->getNextSlugNumber($value); // checks DB > if (0 < $number) { $value .= "-$number"; } > return $value; > } > > Currently we have to make assignment gymnastics even for use cases that > do not require an immutable second value. Would argue many people in PHP > do and will use pipes for readability, not because they suddenly write > PHP from a functional programming point of view. > > Nick
Well said, Nick. Exactly this, pipes are a readability tool in PHP, not a signal that we're writing pure FP like Haskell.
> This is a good proposal, IMO.
Thank you! That means a lot. On Friday, July 17th, 2026 at 13:07, Alex Pătrănescu <drealecs@gmail.com> wrote:
> I would argue that is a very bad practice in php, to alter the actual > function parameter variable. That is because any stack trace obtained will > not reflect the initial value but the modified value. > > And generally, it is a bad practice to override a variable with some other > value that represents something different. You could have had > incrementally: $lowercaseValue, and $slug/$valueWithSlugNumber. > > Alex
I wouldn't call it "very bad practice", it may not be the "best" practice but it is still extremely common in PHP codebases and the language has never discouraged it. We're not the parameter reassignment police 🙃. That said, `|>=` isn't even limited to parameters; it works on properties, array dimensions, and locals. $this->message |>= trim(...); That's the same pattern as `$this->count += 1`. The type and semantic meaning don't change; it's the same data, transformed. PHP already has `$x .= ' suffix'` instead of requiring `$suffixedX = $x . ' suffix'`. Nobody argues `.=` encourages bad practice. `|>=` is the same pattern; a transformation, not a replacement with something semantically different. Using different variable names (`$lowercaseValue`, `$slug`) is a valid stylistic/preference choice. But in practice, people reuse variables for sequential transforms, and `|>=` just makes that existing pattern cleaner. On Friday, July 17th, 2026 at 09:54, Holly Schilling <holly.a.schilling@outlook.com> wrote:
> While I agree, we need to accept that often people do not use the best > practices when coding. PHP makes the barrier to entry low, which invites > people who are still learning what best practices are. > > I wanted to argue against this for exactly this reason, but it's really > not that bad. When combined with FCC, PFA, and pipe chaining, it can > really condense code. > > Holly
Agreed! The more I've played around with this the more I've come to love how expressive and concise it is.
> My only hesitation is that what we're going to end up with is a lot of: > ``` > $foo |>= a(…) > $foo |>= b(…) > $foo |>= c(…) > ``` > This completely defeats the spirit of this operation (and probably has > terrible performance).
Even if folks do choose to write it that way then I would argue that it is still cleaner than: $foo = a($foo); $foo = b($foo); $foo = c($foo); But I think the operator naturally encourages piping, so I don't think it will be too much of an issue: $foo |>= a(...) |> b(...) |> c(...); Now I imagine that you will (potentially) see a lot of regular function / method calls using this to avoid having to repeat the variable expression: // before $someVeryLongVariableName = array_values($someVeryLongVariableName); // after $someVeryLongVariableName |>= array_values(...); On the performance note, there should be zero overhead. Each `|>=` compiles to the exact same opcodes as `$x = $x |> ...`; there is no difference. For complex LHS expressions like the following, `|>=` is actually *more* performant (because it evaluates sub-expressions once instead of twice, same memoization mechanism as `??=`) and more concise (how do you beat that?): //before $array[$this->computeKey($object)] = strtolower($array[$this->computeKey($object)]); // or you introduce a temp var $key = $this->computeKey($object); $array[$key] = strtolower($array[$key]); // after: performant and concise without having to use temp var $array[$this->computeKey($object)] |>= strtolower(...); Best, Caleb

Vadim Dvorovenko

44 days ago
Let me try to rephrase Larry's idea. The pipe operator made its way into PHP from functional programming languages, where immutability is a key aspect of the language's behavior. In those languages, it enables code that is both more productive and freer from side effects. The goal of bringing such operators into PHP is to enhance the language's predictability and minimize side effects, gradually shifting the coding style from imperative to more functional—rather than simply providing a bit of convenient syntactic sugar. Attempting to transform such an operator from an immutable, functional construct into a mutable, imperative one steers the language in the wrong direction and undoes previous efforts. Therefore, the ability to simplify the expression `$params['current']['pallet_cost'] = floatval($params['current']['pallet_cost'])` does not actually improve this code. This code and other examples are initially designed to mutate the original array rather than returning a new one with corrected types. It also uses `floatval`/`intval` instead of the faster native type casts `(float)`/`(int)`. If you rewrite this code using native casts, the pipe won't be applicable to this case at all. You’re pointing to the Laravel experience. But in Laravel, most operations involving collections (with the exception of `transform`, where it is explicitly stated otherwise) and arrays (using the `Arr` helper) are actually performed immutably. Those helpers for immutability and method chaining were introduced in Laravel a long time ago precisely because the language lacked convenient built-in tools for such tasks. If you want mutability, you can always intoroduce a helper in a specific project. ``` function apply(&$value, callable $callback) {     return $value = $callback($value); } ``` аnd call ``` apply($params['current']['pallet_cost'], floatval(...)); ``` You also cite the example `$model |>= ltrim(?)` and compare it to `$x .= 'yyy'`, but the scenarios are different. In `$x .= 'yyy'`, the right-hand side doesn't depend on `$x`, so there’s no cognitive overhead. In `$model |>= ltrim(?)`, however, the right-hand side depends on the variable from the left via the `?` placeholder, creating a mind-bending circular dependency. `$model` goes into `ltrim` and then comes back out; that is far more convoluted than simply appending to a string or incrementing/decrementing a value. That is likely why assignment operators like `.=`, `+=`, and `-=` are used much more frequently than others—they are easier to grasp than an operation like `$b %= $a`. Why do you see `$filters = collect($filters)->map()->all();` in Laravel project code more often than `transform($filters)`? Because developers also write in JavaScript, which lacks a `transform` method. Consequently, the `map` logic is more familiar to them, as it behaves predictably in both languages. And why doesn't JavaScript have a similar `transform` method? Because it can lead to unpredictable side effects. For example, if a handler accesses not only the current element but the entire collection as well, it is completely unclear whether the handler for the second element will see the first element in its modified state or its original one. The approach involving an immutable map and assignment after the entire array has been processed creates more predictable behavior. It is precisely this immutability of the source array that allows certain languages ​​to process elements within a map in parallel or employ other optimizations without the risk of side effects or race conditions. If I understand correctly, Larry wants the language to move in precisely this direction. 18.07.2026 3:01, Caleb White пишет:
> Hi everyone, thanks for the feedback. > > On Friday, July 17th, 2026 at 13:08, Larry Garfield <larry@garfieldtech.com> wrote: >> Perhaps weirdly, I am not a huge fan of this RFC. I'm open to pipe-compound operators (the >> other that's been suggested is a null-safe ?|>, which I'd support), but I'm not sure of the >> use case for this one. >> >> That may be because, from a functional programming point of view, piping a back to itself makes >> little if any sense. Values should be immutable, so you would be doing >> >> $b = $a |> foo(...) |> bar(...) |> baz(...); >> >> I cannot think of a case where I would want to put $a on the left side, too. How realistic is this >> use case? >> >> I don't think this RFC would cause any harm, I suppose, so I probably won't vote against >> it. But at the moment I don't see a compelling reason to vote for it. A concrete real-world >> use case would help make that case, because I cannot come up with one myself. >> >> --Larry Garfield > I understand the FP perspective, but PHP isn't an immutable language. > We mutate variables constantly; that's why `+=`, `.=`, and `??=` exist. > The motivation for this RFC came from seeing this pattern and wishing > that such an operator existed.
-- -- Vadim Dvorovenko

Larry Garfield

43 days ago
On Sun, Jul 19, 2026, at 12:37 AM, Vadim Dvorovenko wrote:
> Let me try to rephrase Larry's idea. > > The pipe operator made its way into PHP from functional programming > languages, where immutability is a key aspect of the language's > behavior. In those languages, it enables code that is both more > productive and freer from side effects. > > The goal of bringing such operators into PHP is to enhance the > language's predictability and minimize side effects, gradually shifting > the coding style from imperative to more functional—rather than simply > providing a bit of convenient syntactic sugar. > > Attempting to transform such an operator from an immutable, functional > construct into a mutable, imperative one steers the language in the > wrong direction and undoes previous efforts. > > > > Therefore, the ability to simplify the expression > `$params['current']['pallet_cost'] = > floatval($params['current']['pallet_cost'])` does not actually improve > this code. This code and other examples are initially designed to mutate > the original array rather than returning a new one with corrected types. > It also uses `floatval`/`intval` instead of the faster native type casts > `(float)`/`(int)`. If you rewrite this code using native casts, the pipe > won't be applicable to this case at all. > > You’re pointing to the Laravel experience. But in Laravel, most > operations involving collections (with the exception of `transform`, > where it is explicitly stated otherwise) and arrays (using the `Arr` > helper) are actually performed immutably. Those helpers for immutability > and method chaining were introduced in Laravel a long time ago precisely > because the language lacked convenient built-in tools for such tasks. > > If you want mutability, you can always intoroduce a helper in a specific > project. > ``` > function apply(&$value, callable $callback) { >     return $value = $callback($value); > } > ``` > аnd call > ``` > apply($params['current']['pallet_cost'], floatval(...)); > ``` > > You also cite the example `$model |>= ltrim(?)` and compare it to `$x .= > 'yyy'`, but the scenarios are different. In `$x .= 'yyy'`, the > right-hand side doesn't depend on `$x`, so there’s no cognitive > overhead. In `$model |>= ltrim(?)`, however, the right-hand side depends > on the variable from the left via the `?` placeholder, creating a > mind-bending circular dependency. `$model` goes into `ltrim` and then > comes back out; that is far more convoluted than simply appending to a > string or incrementing/decrementing a value. That is likely why > assignment operators like `.=`, `+=`, and `-=` are used much more > frequently than others—they are easier to grasp than an operation like > `$b %= $a`. > > Why do you see `$filters = collect($filters)->map()->all();` in Laravel > project code more often than `transform($filters)`? Because developers > also write in JavaScript, which lacks a `transform` method. > Consequently, the `map` logic is more familiar to them, as it behaves > predictably in both languages. And why doesn't JavaScript have a similar > `transform` method? Because it can lead to unpredictable side effects. > For example, if a handler accesses not only the current element but the > entire collection as well, it is completely unclear whether the handler > for the second element will see the first element in its modified state > or its original one. The approach involving an immutable map and > assignment after the entire array has been processed creates more > predictable behavior. It is precisely this immutability of the source > array that allows certain languages ​​to process elements within a map > in parallel or employ other optimizations without the risk of side > effects or race conditions. If I understand correctly, Larry wants the > language to move in precisely this direction.
Impressively, I think this explanation stated my position better than I could. :-) Yes, I am in favor of pushing PHP in a more-functional, mostly-immutable direction (without going all the way to pathological purity like in Haskell). A variant of pipe that is intrinsically built on mutable variables goes against the intent. Yes, PHP is not an inherently immutable language today, but you can easily use it that way if you're careful and know where the edges are where you shouldn't. I think the above description has actually pushed me over into the No category on this RFC. (Which doesn't mean I'm necessarily in favor of the alternate |>= proposal. I'm still pondering that one.) I do agree that some longer-term planning around what alternate pipe forms make sense is wise, and a conversation I'm open to having. But not for a few weeks, as we should be focused on 8.6 at the moment, and none of these will make it into 8.6. --Larry Garfield

Tim Düsterhus

43 days ago
Hi On 2026-07-20 04:11, Larry Garfield wrote:
> Impressively, I think this explanation stated my position better than I > could. :-) Yes, I am in favor of pushing PHP in a more-functional, > mostly-immutable direction (without going all the way to pathological > purity like in Haskell). A variant of pipe that is intrinsically built > on mutable variables goes against the intent. Yes, PHP is not an > inherently immutable language today, but you can easily use it that way > if you're careful and know where the edges are where you shouldn't.
Nothing about `|>` is unique to functional programming or immutability, it's just another way of writing a function call. I disagree with trying to academically gatekeep functionality that is entirely consistent with PHP’s current semantics in an attempt to push PHP into any specific paradigm, particularly when it’s a paradigm that does not match how a majority of PHP code is written in practice. With regard to “you shouldn't modify variables in-place”, I'd like to note that Rust, a language where variables are immutable by default, supports reassigning a variable to be of a different type *in spirit* by redeclaring and thus shadowing the previous variable. In some cases this is even necessary to satisfy the borrow checker. Of course, PHP doesn’t come with the technical consideration of a borrow checker, but incrementally refining a value is nevertheless a common pattern - something I also do in Rust, even when not technically required - and I find that the RFC makes a good example with the “Sequential Processing” (https://wiki.php.net/rfc/pipe_assignment_operator#sequential_processing).
> and none of these will make it into 8.6.
This is false: The featured RFC had its last change on July 14th (which I consider to be a minor change), and the last major change on July, 13th. This means it may open voting starting July 27th, ending August 10th and meeting the soft freeze deadline. Even if we consider the change on the 14th to be a major change, it may (barely) meet the deadline. Best regards Tim Düsterhus

Bob Weinand

43 days ago
Hey Caleb,
> Am 20.07.2026 um 04:11 schrieb Larry Garfield <larry@garfieldtech.com>: > > Impressively, I think this explanation stated my position better than I could. :-) Yes, I am in favor of pushing PHP in a more-functional, mostly-immutable direction (without going all the way to pathological purity like in Haskell). A variant of pipe that is intrinsically built on mutable variables goes against the intent. Yes, PHP is not an inherently immutable language today, but you can easily use it that way if you're careful and know where the edges are where you shouldn't. > > I think the above description has actually pushed me over into the No category on this RFC. (Which doesn't mean I'm necessarily in favor of the alternate |>= proposal. I'm still pondering that one.) > > I do agree that some longer-term planning around what alternate pipe forms make sense is wise, and a conversation I'm open to having. But not for a few weeks, as we should be focused on 8.6 at the moment, and none of these will make it into 8.6. > > --Larry Garfield
sorry that you had to read this mail; Larry often has ideas that don't work well in practice - and then core devs have to shoot this down. Please just ignore this. Bob

Larry Garfield

43 days ago
On Mon, Jul 20, 2026, at 11:38 AM, Bob Weinand wrote:
> Hey Caleb, > >> Am 20.07.2026 um 04:11 schrieb Larry Garfield <larry@garfieldtech.com>: >> >> Impressively, I think this explanation stated my position better than I could. :-) Yes, I am in favor of pushing PHP in a more-functional, mostly-immutable direction (without going all the way to pathological purity like in Haskell). A variant of pipe that is intrinsically built on mutable variables goes against the intent. Yes, PHP is not an inherently immutable language today, but you can easily use it that way if you're careful and know where the edges are where you shouldn't. >> >> I think the above description has actually pushed me over into the No category on this RFC. (Which doesn't mean I'm necessarily in favor of the alternate |>= proposal. I'm still pondering that one.) >> >> I do agree that some longer-term planning around what alternate pipe forms make sense is wise, and a conversation I'm open to having. But not for a few weeks, as we should be focused on 8.6 at the moment, and none of these will make it into 8.6. >> >> --Larry Garfield > > sorry that you had to read this mail; Larry often has ideas that don't > work well in practice - and then core devs have to shoot this down. > Please just ignore this. > > Bob
Bob, this is an extremely inappropriate email to send. All sorts of people disagree with all sorts of proposals for all sorts of reasons. All sorts of people "often have ideas that won't work well in practice." That's the whole point of a list discussion: To let those differences shake out and find the stuff that does work that people can agree on. Singling out one person (who has been involved in several successful RFCs) and implying that person is some sort of idea-troll to be specifically ignored is grossly inappropriate, and I would expect better of someone of your stature. --Larry Garfield

Vadim Dvorovenko

44 days ago
Hello, Caleb. Firtly, i’d like to point out that you aren’t the first person to come up with the idea of ​​combining assignment and pipeline operators, and inroduce `|>=` operator Take a look at discussion, https://news-web.php.net/php.internals/128141 . RFC draft is here https://github.com/vadimonus/php-rfc/blob/main/ltr-assignment.md. I haven't submitted these drafts as an RFC yet because I haven't received enough positive feedback on the first RFC in the chain: https://wiki.php.net/rfc/pipe_to_return.  You can see another drafts in github. The main idea, is that pipe operator reverses traditional funcation call reading order, so we need some more operators with same order to use together to reduce cognitive load. Your variant of this operator makes traditional rigth to left action, like other action. But `|>` arrow visually defines opposite direction. This may lead to incorrect perception, increase cognitive load and lead to mistakes. I think, all extensions of pipe operator should be ducsussed together to intorduce non conflicting group of operators.  Please add  to your RFC links to other discussions and theese RFC drafts. 10.07.2026 11:45, Caleb White пишет:
> Hi internals, > > I'd like to open discussion on my (first!) RFC for the pipe assignment operator (|>=): > https://wiki.php.net/rfc/pipe_assignment_operator > > It adds a compound assignment form of the pipe operator, so that > $x |>= callable is shorthand for $x = $x |> callable, with > support for chaining. Implementation with tests is at: > https://github.com/php/php-src/pull/22633 > > Looking forward to your feedback. > > Thanks! > Caleb
-- -- Vadim Dvorovenko

Caleb White

44 days ago
On Saturday, July 19th, 2026 at 04:20, Vadim Dvorovenko <vadim.dvorovenko@gmail.com> wrote:
> Firtly, i'd like to point out that you aren't the first person to come > up with the idea of combining assignment and pipeline operators, and > inroduce `|>=` operator > > Take a look at discussion, > https://news-web.php.net/php.internals/128141 . RFC draft is here > https://github.com/vadimonus/php-rfc/blob/main/ltr-assignment.md. > > I haven't submitted these drafts as an RFC yet because I haven't > received enough positive feedback on the first RFC in the chain: > https://wiki.php.net/rfc/pipe_to_return. You can see another drafts > in github.
Hi Vadim, Thanks for the pointer, interesting to see that the idea of combining assignment with the pipe operator has come up before. Great minds! I did take a look at your pipe-to-return RFC and the LTR assignment draft. These are fundamentally different proposals from what this RFC does, though. Your `|>=` reverses assignment direction entirely (`expr |>= $var` means `$var = expr`), whereas mine is a compound assignment in the traditional sense (`$var |>= callable` means `$var = $var |> callable`), the same pattern as `+=`, `.=`, and `??=`.
> The main idea, is that pipe operator reverses traditional funcation > call reading order, so we need some more operators with same order to > use together to reduce cognitive load. > > Your variant of this operator makes traditional rigth to left action, > like other action. But `|>` arrow visually defines opposite direction. > This may lead to incorrect perception, increase cognitive load and > lead to mistakes.
The scope is quite different. Your drafts introduce an entirely new assignment direction for PHP along with a full family of LTR compound operators (`|> +=`, `|> -=`, `|> .=`, etc.). That's a significantly larger surface area change. I'd gently push back on the premise that `$result = expr |> f(...) |> g(...)` "reverses traditional function call reading order". Pipes don't reverse reading order, they fix it; nested calls read inside-out (`g(f(expr))`), and pipes linearize that left-to-right. Assignment on the left is just how every C-family language works; nobody reads `$result = 1 + 2` and feels a directional conflict. Every language with pipes (F#, Elixir, OCaml, Hack) keeps `var = expr |> ...` and none of them have introduced LTR assignment to complement it. Even if those proposals were accepted, I think most PHP developers would still reach for `$var = expr` out of habit and familiarity. So `|>=` as a compound assignment operator would still have independent value; it makes the very common `$x = transform($x)` pattern cleaner regardless of whether LTR assignment exists.
> I think, all extensions of pipe operator should be ducsussed together > to intorduce non conflicting group of operators. Please add to your > RFC links to other discussions and theese RFC drafts.
I don't think it makes sense to bundle these together or gate one on the other. They solve different problems and can be evaluated on their own merits. As for adding links to your drafts in my RFC, I'd prefer to keep it focused on its own proposal. You're of course welcome to cross-reference my RFC from your drafts if you'd like. Best, Caleb

Vadim Dvorovenko

44 days ago
Yes, I have carefully studied the RFCs and understand that they deal with completely different syntax and use cases. However, both proposals advocate for adding and using the `|>=` operator. Attempting to use it for both scenarios would result in a grammar conflict (the case `$x |>= $y` must be interpreted unambiguously). Therefore, it is appropriate to point out that this is not the only RFC proposing the `|>=` combination. 19.07.2026 11:54, Caleb White пишет:
> On Saturday, July 19th, 2026 at 04:20, Vadim Dvorovenko <vadim.dvorovenko@gmail.com> wrote: >> Firtly, i'd like to point out that you aren't the first person to come >> up with the idea of combining assignment and pipeline operators, and >> inroduce `|>=` operator >> >> Take a look at discussion, >> https://news-web.php.net/php.internals/128141 . RFC draft is here >> https://github.com/vadimonus/php-rfc/blob/main/ltr-assignment.md. >> >> I haven't submitted these drafts as an RFC yet because I haven't >> received enough positive feedback on the first RFC in the chain: >> https://wiki.php.net/rfc/pipe_to_return. You can see another drafts >> in github. > Hi Vadim, > > Thanks for the pointer, interesting to see that the idea of combining > assignment with the pipe operator has come up before. Great minds! > > I did take a look at your pipe-to-return RFC and the LTR assignment > draft. These are fundamentally different proposals from what this RFC > does, though. Your `|>=` reverses assignment direction entirely > (`expr |>= $var` means `$var = expr`), whereas mine is a compound > assignment in the traditional sense (`$var |>= callable` means > `$var = $var |> callable`), the same pattern as `+=`, `.=`, and `??=`. > >> The main idea, is that pipe operator reverses traditional funcation >> call reading order, so we need some more operators with same order to >> use together to reduce cognitive load. >> >> Your variant of this operator makes traditional rigth to left action, >> like other action. But `|>` arrow visually defines opposite direction. >> This may lead to incorrect perception, increase cognitive load and >> lead to mistakes. > The scope is quite different. Your drafts introduce an entirely > new assignment direction for PHP along with a full family of LTR > compound operators (`|> +=`, `|> -=`, `|> .=`, etc.). That's a > significantly larger surface area change. I'd gently push back > on the premise that `$result = expr |> f(...) |> g(...)` "reverses > traditional function call reading order". Pipes don't reverse reading > order, they fix it; nested calls read inside-out (`g(f(expr))`), and > pipes linearize that left-to-right. Assignment on the left is just > how every C-family language works; nobody reads `$result = 1 + 2` > and feels a directional conflict. Every language with pipes > (F#, Elixir, OCaml, Hack) keeps `var = expr |> ...` and none of > them have introduced LTR assignment to complement it. > > Even if those proposals were accepted, I think most PHP developers > would still reach for `$var = expr` out of habit and familiarity. > So `|>=` as a compound assignment operator would still have independent > value; it makes the very common `$x = transform($x)` pattern cleaner > regardless of whether LTR assignment exists. > >> I think, all extensions of pipe operator should be ducsussed together >> to intorduce non conflicting group of operators. Please add to your >> RFC links to other discussions and theese RFC drafts. > I don't think it makes sense to bundle these together or gate one on > the other. They solve different problems and can be evaluated on their > own merits. As for adding links to your drafts in my RFC, I'd prefer > to keep it focused on its own proposal. You're of course welcome to > cross-reference my RFC from your drafts if you'd like. > > Best, > Caleb >
-- -- Vadim Dvorovenko

Caleb White

42 days ago
On Sunday, July 19th, 2026 at 01:04, Vadim Dvorovenko <vadim.dvorovenko@gmail.com> wrote:
> Yes, I have carefully studied the RFCs and understand that they deal > with completely different syntax and use cases. However, both proposals > advocate for adding and using the `|>=` operator. Attempting to use it > for both scenarios would result in a grammar conflict (the case `$x |>= > $y` must be interpreted unambiguously). Therefore, it is appropriate to > point out that this is not the only RFC proposing the `|>=` combination. > > Vadim Dvorovenko
I see that you formally published your RFC yesterday---I'll link to it in my references. Best, Caleb

Nick

44 days ago
Hey Caleb, On 10.07.26 11:45, Caleb White wrote:
> Hi internals, > > I'd like to open discussion on my (first!) RFC for the pipe assignment operator (|>=): > https://wiki.php.net/rfc/pipe_assignment_operator > > It adds a compound assignment form of the pipe operator, so that > $x |>= callable is shorthand for $x = $x |> callable, with > support for chaining. Implementation with tests is at: > https://github.com/php/php-src/pull/22633 > > Looking forward to your feedback. > > Thanks! > Caleb
Thanks for the RFC! As you already could guess I am in support. Been running your implementation and didn't run into anything unexpected, nor was I able to break it in different ways than the current pipe behaviour. Though, I'd like to add the following. 1) This was feeling nitpicky at first, but it doesn't leave me alone since I first read your RFC. :) Now, given what Vadim added to the discussion, I think it is worth bringing it up. Right now we are doing: ``` $someVar = $someVar |> array_filter(...); ``` the RFC allows to omit the noise: ``` $someVar =                    |> array_filter(...); ``` you see where I am going; now let's remove the white space: ``` $someVar =|> array_filter(...); ``` my point is: why `|>=` and not `=|>`? I think the latter would be more intuitive: assign the result of piping to the variable. I know that `|>=` follows the established `foo=` convention for compound assignments like `??=` or `.=`; which is an argument in its favour. Still, I think `=|>` better communicates how this particular operation expands. Especially when considering future additions like the ones Vadim proposes in future scope. Because a side effect of having `=|>` would be that the right hand side of `|>` remains open to extension for potential in-pipe-behaviour modifying features like the ones Vadim proposes -- without the final assignment being affected. As in, `=|>` assigns the pipe result, while `=|>+`, `=|>-`, `=|> .`, `=|>whatever` allow modifying in-pipe behaviour. This would make sense because perhaps these pipe behaviour operators will also be allowed for non-shorthand assigned (`|>+`, `|> -`, `|> .` ) pipes that want the resulting immutable right hand side Larry made an argument for. Having a clear separation between assignment, and potential future additions to modify pipe behaviour makes sense. As in, want to add a modifying operator later? Cool, your assignment remains in tact `=|>`. You just add a modifying operator `=|>-` instead of flipping from `|>=` to `|>-=` which would affect final assignment *and* in-pipe behaviour -- having the modifier out of the final assignment decision is cleaner. Also, it is not impossible that what Vadim proposes in future scope would result in something like `|>=??=` which IMO makes an even stronger point for strictly separating what is proposed here and potential future additions of modifying operators: `=|> .. |> ??=`. Because these *are* different: `... |> ??=` (for in-pipe operations) and `=|> ... |> ??=` (only for the final assignment). Vadims proposal makes sense on it's own, but it currently mixes two concerns: in-pipe operations and final assignment -- which I believe should be separated. Both of your proposals (especially Vadims future scope) should probably rather complement each other instead of competing; I think what I am writing here potentially could make this easier. One additional soft argument is that text ligatures will show >= as ≥ which will just add to the confusion if modifying operators as Vadim proposes in future scope would ever be added. Long story short: `=|>`over `|>=` IMO has a lot of appeal. Though, I know not having `|>=` would deprive us of the "volcano operator" naming; sorry for being the party pooper. 2) Holly brought up this example: ``` $foo |>= a(…) $foo |>= b(…) $foo |>= c(…) ``` and it seems you talked past each other. Hollys example didn't end lines with semicolons, while your answer had them. Currently, the non-semicolon variant: ``` $foo = "hello"; $foo |>= strtoupper(...) // no semicolon $foo |>= strtolower(...); var_dump($foo); ``` throws with "Parse error: syntax error, unexpected variable "$foo" in". In the same way the current ``` $foo = "hello"; $foo |> strtoupper(...) // no semicolon $foo |> strtolower(...); var_dump($foo); ``` throws. I just wanted to point this out because apparently it caused confusion in the discussion. Perhaps worth to clarify the RFC (even though it's also current pipe behaviour). 3) I recently discovered a bug [1] when pipes are combined with property hooks. Unsurprisingly, with your addition it is the same. However, since this shows that pipes are not behaving everywhere identical it would probably be good to add some tests to confirm the interaction of assigned pipes with property hooks, readonly etc. -- and maybe also to clarify it in the RFC. --- Cheers Nick [1] https://github.com/php/php-src/issues/22587

Tim Düsterhus

43 days ago
Hi On 2026-07-19 10:35, Nick Sdot wrote:
> I think the latter would be more intuitive: assign the result of piping > to the variable. I know that `|>=` follows the established `foo=` > convention for compound assignments like `??=` or `.=`; which is an > argument in its favour. Still, I think `=|>` better communicates how > this particular operation expands. Especially when considering future > additions like the ones Vadim proposes in future scope.
I believe language consistency is of utmost importance for users to learn and remember fewer special cases.
> One additional soft argument is that text ligatures will show >= as ≥ > which will just add to the confusion if modifying operators as Vadim > proposes in future scope would ever be added.
It's also not uncommon for them to show |> as ▷, because |> is established as a pipe operator.
> Long story short: `=|>`over `|>=` IMO has a lot of appeal.
I disagree. It looks more like a special form of `=>` rather than an assignment, which loops back to the “consistency” argument above. Best regards Tim Düsterhus

Bob Weinand

43 days ago
Hey,
> Am 20.07.2026 um 14:34 schrieb Tim Düsterhus <tim@bastelstu.be>: > > Hi > > On 2026-07-19 10:35, Nick Sdot wrote: >> I think the latter would be more intuitive: assign the result of piping to the variable. I know that `|>=` follows the established `foo=` convention for compound assignments like `??=` or `.=`; which is an argument in its favour. Still, I think `=|>` better communicates how this particular operation expands. Especially when considering future additions like the ones Vadim proposes in future scope. > > I believe language consistency is of utmost importance for users to learn and remember fewer special cases. > >> One additional soft argument is that text ligatures will show >= as ≥ which will just add to the confusion if modifying operators as Vadim proposes in future scope would ever be added. > > It's also not uncommon for them to show |> as ▷, because |> is established as a pipe operator. > >> Long story short: `=|>`over `|>=` IMO has a lot of appeal. > > I disagree. It looks more like a special form of `=>` rather than an assignment, which loops back to the “consistency” argument above. > > Best regards > Tim Düsterhus
I wholeheartedly agree with Tims assessment here. Also, it's "pipe then assign" - "|>, followed by =". I absolutely don't like the pipe operator, but pipe-assign (plus some pipes afterward possibly) makes a lot of sense. "Transform this variable", without any repetition. I'm in favour of this proposal as a whole too. I just have one more question to the RFC author, which I see in the implementation, but the RFC is not explicitly noting: Is it intentional that fetching is repeated? It will literally desugar $a->b->c |>= strtolower(...); to $a->b->c |>= strtolower($a->b->c); resulting in double execution of e.g. property get hooks. Which in my opinion ought not be the proper behaviour. I acknowledge, that the behaviour is slightly different from the generic operator-assign that other unrelated code can be accessed in between, making RW fetch indirects unsafe - this could obviously be solved perfectly with ad-hoc references in cases the container is an indirect after RW fetching. (i.e. $a[0][0] |>= intval(...); could be like $_container = &$a[0]; $_container[0] |>= intval($_container[0]); - for objects containers or non-nested stuff, it's obviously unneeded.) Which would the be quite close to actual semantics of other assign-ops. Nice job on the RFC, Bob

Tim Düsterhus

43 days ago
Hi On 2026-07-20 16:55, Bob Weinand wrote:
> I just have one more question to the RFC author, which I see in the > implementation, but the RFC is not explicitly noting: > Is it intentional that fetching is repeated?
I would consider that a bug in the implementation, given that the “Single-Evaluation Guarantee” section mentions:
> When the LHS contains sub-expressions, they are evaluated exactly once:
and
> This is the same guarantee that ??= provides over $x = $x ?? default, > implemented using the same compile-time memoization mechanism.
Thus if it behaves differently to `??=`, it's a bug in the implementation :-) Best regards Tim Düsterhus

Caleb White

42 days ago
On Monday, July 20th, 2026 at 14:55, Bob Weinand <bobwei9@hotmail.com> wrote:
> I just have one more question to the RFC author, which I see in the > implementation, but the RFC is not explicitly noting: > Is it intentional that fetching is repeated? > It will literally desugar $a->b->c |>= strtolower(...); to > $a->b->c = strtolower($a->b->c); resulting in double execution > of e.g. property get hooks.
On Monday, July 20th, 2026 at 15:24, Tim Düsterhus <tim@bastelstu.be> wrote:
> I would consider that a bug in the implementation, given that the > "Single-Evaluation Guarantee" section mentions: > > When the LHS contains sub-expressions, they are evaluated > exactly once: > > Thus if it behaves differently to `??=`, it's a bug in the > implementation :-)
Hi Bob, Tim, Thanks for flagging this. I tested the scenario Bob described and `|>=` behaves identically to `??=` here: class Inner { public string $c = "hello" { get { echo "Inner::c GET\n"; return $this->c; } set(string $v) { echo "Inner::c SET\n"; $this->c = $v; } } } class Outer { public Inner $b { get { echo "Outer::b GET\n"; return $this->b; } } public function __construct() { $this->b = new Inner(); } } $a = new Outer(); $a->b->c |>= strtoupper(...); // Outer::b GET (read) // Inner::c GET (read) // Outer::b GET (write-back) // Inner::c SET (write-back) $a->b->c ??= "default"; // Outer::b GET (read) // Inner::c GET (read) // Outer::b GET (write-back) // Inner::c SET (write-back) Both `|>=` and `??=` fetch the intermediate chain twice (once for the read, once for the write-back). The single-evaluation guarantee in the RFC refers to sub-expressions like `$arr[expensive_call()]`, where the call itself is evaluated only once. That works correctly: $arr[track()] |>= strtoupper(...); // track() is called exactly once So the behavior is consistent with `??=`. Bob, your observation about optimizing intermediate chain fetches with ad-hoc references is interesting, but that would be an improvement to all compound assignment operators, not something specific to `|>=`. I've updated the RFC to clarify this in the Single-Evaluation Guarantee section. On Sunday, July 19th, 2026 at 08:35, Nick Sdot <php@nicksdot.dev> wrote:
> 1) my point is: why `|>=` and not `=|>`?
Hi Nick, Tim already covered this well, but I agree with him: `|>=` follows the established `op=` convention for compound assignments (`+=`, `.=`, `??=`). `=|>` looks like a special form of `=>` rather than an assignment, and consistency with existing patterns is worth more than theoretical future extensibility for operators that may never materialize.
> 2) Holly's example without semicolons
Yeah, that was just a missing semicolon in the email example; standard parse error, same as with `|>`. Nothing to address there.
> 3) I recently discovered a bug [1] when pipes are combined with > property hooks.
Thanks for flagging this. I've added a test (assign_pipe_018.phpt) that covers `|>=` with get/set hooks, virtual properties, and readonly properties. The `|>=` side works correctly; the bug you found (#22587) is specific to the base `|>` operator and is not introduced or affected by this RFC. Thanks for testing the implementation and for the detailed feedback! Best, Caleb

Tim Düsterhus

41 days ago
Hi On 2026-07-21 06:18, Caleb White wrote:
> So the behavior is consistent with `??=`. Bob, your observation about > optimizing intermediate chain fetches with ad-hoc references is > interesting, but that would be an improvement to all compound > assignment operators, not something specific to `|>=`. > > I've updated the RFC to clarify this in the Single-Evaluation > Guarantee section.
Thank you. The clarification makes sense to me and I don't have further comments on the RFC. As indicated in https://news-web.php.net/php.internals/132049, your RFC could still be included in PHP 8.6. Even with this clarification, which is a “minor change” you would be just in time. Any further change to the RFC text will miss the deadline. *If* you want to try to get into PHP 8.6, you'll need to open voting on the 28th of July very shortly after 04:18 UTC until August 11th the same time + a bit of buffer. You will also need to send an intent to vote email at least 48 hours before that. The decision is up to you. I just wanted to provide you with all the necessary information as a first-time RFC author to make an adequate decision. Best regards Tim Düsterhus

Caleb White

40 days ago
On Wednesday, July 22nd, 2026 at 09:54, Tim Düsterhus <tim@bastelstu.be> wrote:
> Thank you. The clarification makes sense to me and I don't have further > comments on the RFC. > > As indicated in https://news-web.php.net/php.internals/132049, your RFC > could still be included in PHP 8.6. Even with this clarification, which > is a “minor change” you would be just in time. Any further change to the > RFC text will miss the deadline. > > *If* you want to try to get into PHP 8.6, you'll need to open voting on > the 28th of July very shortly after 04:18 UTC until August 11th the same > time + a bit of buffer. You will also need to send an intent to vote > email at least 48 hours before that. The decision is up to you. I just > wanted to provide you with all the necessary information as a first-time > RFC author to make an adequate decision. > > Best regards > Tim Düsterhus
Hi Tim, Thank you for all your help, patience, and guidance throughout this process, especially as a first-time RFC author. And I really appreciate you going to bat for this RFC in the thread---thanks again. I do intend to try to get this into 8.6. Here's the schedule I'm planning: - Intent to vote: within the next day or so - Open voting: Monday July 28th ~04:30 UTC - Voting closes: Monday August 11th ~04:30 UTC If the vote passes, what's the process for getting the PR merged? Best, Caleb

Caleb White

40 days ago
On Wednesday, July 22nd, 2026 at 13:51, Caleb White <cdwhite3@pm.me> wrote:
> Hi Tim, > > Thank you for all your help, patience, and guidance throughout this > process, especially as a first-time RFC author. And I really appreciate > you going to bat for this RFC in the thread---thanks again. > > I do intend to try to get this into 8.6. Here's the schedule I'm planning: > - Intent to vote: within the next day or so > - Open voting: Monday July 28th ~04:30 UTC > - Voting closes: Monday August 11th ~04:30 UTC > > If the vote passes, what's the process for getting the PR merged? > > Best, > Caleb
Apparently I got my days mixed up---07-28 and 08-11 are Tuesdays Best, Caleb

Tim Düsterhus

40 days ago
Hi On 7/22/26 20:51, Caleb White wrote:
> I do intend to try to get this into 8.6. Here's the schedule I'm planning: > - Intent to vote: within the next day or so > - Open voting: Monday July 28th ~04:30 UTC > - Voting closes: Monday August 11th ~04:30 UTC
Except for the week-day correction that you noticed yourself, that would be fully in line with policy and would also be meeting the soft freeze deadline.
> If the vote passes, what's the process for getting the PR merged?
If the vote looks favorable, I'll also have a look at the implementation (so far I only looked at the tests, I also just added another test review) and if it looks good to me then I'll find a second reviewer for the implementation. You'll just have to make sure to react on the review notes in a timely fashion. That should hopefully result in the technical review being concluded before the vote ends, so that the PR is immediately ready for merging. Given that August 11 is also the day where Beta 1 is tagged, I'll ask the RMs to merge the PR (if vote is accepted and implementation is ready, of course) before tagging to avoid any timezone scheduling issues. After that, PRs may only land with RM approval, but given it’s a localized change and a small PR, I don't expect the approval to be denied, but I obviously can’t speak for certain. Best regards Tim Düsterhus

Caleb White

40 days ago
On Thursday, July 9th, 2026 at 23:45, Caleb White <cdwhite3@pm.me> wrote:
> Hi internals, > I'd like to open discussion on my (first!) RFC for the pipe assignment operator (|>=): > https://wiki.php.net/rfc/pipe_assignment_operator > > It adds a compound assignment form of the pipe operator, so that > $x |>= callable is shorthand for $x = $x |> callable, with > support for chaining. Implementation with tests is at: > https://github.com/php/php-src/pull/22633 > > Looking forward to your feedback. > > Thanks! > Caleb
Hi folks, The discussion started 2026-07-09, last minor change was 2026-07-21 04:21 UTC; therefore, the 7-day cooldown expires at 2026-07-28 04:21 UTC. I intend to open voting on the Pipe Assignment Operator RFC on 2026-07-28 at ~04:30 UTC. Thanks to everyone who provided feedback during discussion. Best, Caleb