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