Skip to content

Conversation

zKoz210
Copy link
Contributor

@zKoz210 zKoz210 commented Aug 27, 2025

Support BackedEnum in Collection::keyBy()

Description

This PR extends Laravel’s Collection::keyBy() method to natively support PHP BackedEnum.

Currently, when passing an enum instance as the key, the resulting associative array would contain the enum object itself as the array key, which is not practical in most use cases.

With this change, if the resolved key is an instance of \BackedEnum, it will automatically use its backed value (string or int) instead of the enum object.


Motivation

  • PHP 8.1 introduced Enums, and they are now widely used as identifiers in Laravel applications (e.g. status, types, categories).
  • When working with collections, developers often need to group or key collections by enum values.
  • In PHP, array keys must be int or string. If an object is used, PHP will silently cast it to a string such as "Object id #123", which is not meaningful or stable.
  • This fix ensures that when a BackedEnum is used as a key, its backed value (string|int) is used instead, providing predictable and useful keys.

Example Usage

enum Status: string {
    case ACTIVE = 'active';
    case INACTIVE = 'inactive';
}

$items = collect([
    ['id' => 1, 'status' => Status::ACTIVE],
    ['id' => 2, 'status' => Status::INACTIVE],
]);

$result = $items->keyBy('status');

//    Error Object of class App\Framework\Models\Enums\Status could not be converted to string

@@ -576,6 +576,10 @@ public function keyBy($keyBy)
foreach ($this->items as $key => $item) {
$resolvedKey = $keyBy($item, $key);

if ($resolvedKey instanceof \BackedEnum) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not accept any enums and use the \Illuminate\Support\enum_value helper?

if ($resolvedKey instanceof \UnitEnum) {
    $resolvedKey = \Illuminate\Support\enum_value($resolvedKey);
}

@taylorotwell taylorotwell marked this pull request as draft August 27, 2025 13:41
Comment on lines 579 to 583
$resolvedKey = $keyBy($item, $key);

if ($resolvedKey instanceof \BackedEnum) {
$resolvedKey = $resolvedKey->value;
if ($resolvedKey instanceof \UnitEnum) {
$resolvedKey = enum_value($resolvedKey);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can even shorten this as enum_value() returns non-enum input unchanged:

Suggested change
$resolvedKey = $keyBy($item, $key);
if ($resolvedKey instanceof \BackedEnum) {
$resolvedKey = $resolvedKey->value;
if ($resolvedKey instanceof \UnitEnum) {
$resolvedKey = enum_value($resolvedKey);
}
$resolvedKey = enum_value($keyBy($item, $key));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants