Hello, internals,
Currently, this is an Error:
$allowedRoles = [Role::Admin];
$hasRoles = [Role::User, Role::Admin];
if(!empty(array_intersect($allowedRoles, $hasRoles))) doSomething();
This is an error because enums cannot be cast to a string (and trying
to make them stringable is not allowed) and many array functions
expect something stringable. To work around this limitation, the above
example must be rewritten like this:
array_uintersect($allowedRles, $hasRoles, fn($l, $r) => $l === $r ? 0 : 1));
I'd like to propose an RFC that allows array functions to accept
stringable values and enum values. Any other values (like general
objects) would be out of scope.
I foresee someone bringing up how the natural order of an enum would
be determined. The order will be determined via the same order as
Enum::cases() outputs, independent of their backed value (e.g.,
lexicographical order as defined in the code), thus the order of
enum Alpha : int { case B = 1; case A = 0; }
would be [ Alpha::B, Alpha::A ]. This is what happens when calling
sort([Alpha::A, Alpha::B]) currently, so I hope this won't be an
issue.
Some example functions that would be impacted by this RFC (I still
haven't dug into all the array functions yet):
- array_intersect
- array_diff
- array_unique? (works with SORT_REGULAR, so this might need
discussion/exemption)
If this has been proposed before, I apologize, as I did search for
something like this before proposing it.
Robert Landers
Software Engineer
Utrecht NL
On Thursday, February 23, 2023, Robert Landers landers.robert@gmail.com
wrote:
Hello, internals,
Currently, this is an Error:
$allowedRoles = [Role::Admin];
$hasRoles = [Role::User, Role::Admin];if(!empty(array_intersect($allowedRoles, $hasRoles))) doSomething();
This is an error because enums cannot be cast to a string (and trying
to make them stringable is not allowed) and many array functions
expect something stringable. To work around this limitation, the above
example must be rewritten like this:array_uintersect($allowedRles, $hasRoles, fn($l, $r) => $l === $r ? 0 :
1));Robert Landers
Software Engineer
Utrecht NL
...I'd like to add as an aside that:
if(!empty(array_intersect($allowedRoles, $hasRoles)))
is more simply written as
if (array_intersect($allowedRoles, $hasRoles))
--
And for anyone unfamiliar with array_udiff_ and array_uintersect_ functions:
-
The two variables in their callback function signature do not relate by
position to the input arrays. This is why it is common to use $a and $b (as
is common when callingusort()). In other words, the first input array's
data may occur as the first parameter in the callback or the second
parameter (like wise with subsequent input arrays). -
The return value from these functions is expected to be an integer from
the result of a three-way comparison -- not the int value of a binary
evaluation. Most simply, make a habit of implementing the spaceship
operator (<=>). See "array_uintersect() gives unexpected results when
callback only returns 0 or 1" @ https://stackoverflow.com/q/8176881/2943403
Another example:
https://stackoverflow.com/a/71049380/2943403
The deep dive: https://stackoverflow.com/a/70817582/2943403
mickmackusa