Skip to content

using afterQuery on a relationship does not end up retaining any set custom keys #57612

@Jade-GG

Description

@Jade-GG

Laravel Version

12.36.1

PHP Version

8.3.24

Database Driver & Version

No response

Description

When you're using afterQuery on an Eloquent relationship, with something like:

return $this->hasMany(Product::class)
    ->afterQuery(fn ($result) => $result->keyBy('product_id'));

The custom keys will be thrown away and replaced with standard incrementing keys (i.e. it turns back into a standard array). After a lot of searching I found out that this is seemingly caused by the buildDictionary function used in every relationship, which ignores custom keys completely and re-keys every array it comes across.

For most relationships a fix for this would be fairly straightforward, for example BelongsToMany could be changed like this:

-        foreach ($results as $result) {
+        foreach ($results as $key => $result) {
            $value = $this->getDictionaryKey($result->{$this->accessor}->{$this->foreignPivotKey});

-            $dictionary[$value][] = $result;
+            $dictionary[$value][$key] = $result;
        }

For HasOneOrMany it's a bit more involved, but still possible.

However, I do not know whether there would be any relevant knock-on effects from changing this behavior, which makes me uncertain whether it's a good idea to go through and fix all of them and create a pull request with that. Plus, there might be a better solution here that I don't know about.

Steps To Reproduce

  1. Create two Eloquent models that relate to each other in some way (e.g. a hasMany relationship)
  2. Relate them with an Eloquent relationship
  3. Try to use ->afterQuery(...) on this relationship with a ->keyBy(...)
  4. Dump what comes out of this relationship and observe that the custom keys you tried to add have been removed.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions