On Fri, Aug 22, 2025, at 22:09, Larry Garfield wrote:
> On Fri, Aug 22, 2025, at 12:45 PM, Kyle Katarn wrote:
> 
> > About "What determines comparability", it follows the usual rules of 
> > PHP: https://www.php.net/manual/en/language.operators.comparison.php
> >
> > So it's equivalent to ($value < $min) ? $min : (($value > $max) ? $max 
> > : $value) and also equivalent to min($max, max($min, $value))
> >
> > About clamp(new Point(1, 2), new Point(0, 0), new Point(5, 5));
> >
> > If Point is a comparable value (simple DTO for example), it should 
> > return $value, like when doing ($value < $min) ? $min : (($value > 
> > $max) ? $max : $value) we could add a test for such case, but I think 
> > that for consistency, whatever currently works in min() should work in 
> > clamp()
> >
> > Following the link of the implementation, there is also a link to the 
> > documentation where I already explained the comparison rules following 
> > the example of what was done in the documentation for min() and max(): 
> > https://github.com/php/doc-en/pull/4814
> 
> Please make sure the above is captured in the RFC.
> 
> Though apparently what PHP currently does with Point comparisons in min/max 
> is... weird.  I don't even know what the logic here is. :)
> 
> https://3v4l.org/pTmiV
> 
> (No need to change it in this RFC, just note explicitly that the expected 
> behavior is identical to that min(max()) construct, regardless of type.)
> 
> --Larry Garfield
> 

It only compares the first property, and if there is a conflict, it moves on to 
the next property. That is why some of us have been advocating for operator 
overrides: because this default isn’t always appropriate, as your Point example 
illustrates. In some cases, you would want to compare magnitude or something 
else entirely, not just the x value.

What is even trickier is that this process completely ignores computed hooks. 
So, if you add a hook as the first property (for example, returning the 
magnitude), it is simply ignored. As a weird side note: if you cast the object 
to an array, the computed hook disappears, but if you use `json_encode()`, the 
computed value is included.

To complicate things further, the current behaviour for objects is actually 
“undefined” and it isn’t documented. There are examples that show how objects 
are compared, but they don’t explicitly mention that the object is being cast 
to an array (see the above paragraph on why that matters). Because this relies 
on implementation details rather than documented behaviour, it could change 
between PHP versions without an RFC. That makes relying on it a bit risky.

Adding operator overrides would help by making this behaviour explicit and 
consistent across versions, or just defining it in general. But whenever 
someone tries to define this more clearly (as I started to do with Records), it 
tends to run into resistance on this list for reasons I’ve never quite 
understood.

— Rob

Reply via email to