Can't combine fetch: EXTRA_LAZY with indexBy: foreign key #5235

Open
opened 2026-01-22 15:02:10 +01:00 by admin · 3 comments
Owner

Originally created by @dragoste on GitHub (Aug 26, 2016).

I found it impossible to use EXTRA_LAZY mode for collection indexed by a relation (foreign key). It may be related to #3978.

Let's suppose we have Parent class with Parent::children collection where Child::user is unique across the collection (one Child per User for each Parent). When we would like to index Parent::children by Child::user property (user_id actually), it works for standard fetch:LAZY mode as implemented in PR #639, which lets us to use column name instead of property name.

Entity\Parent:
  type: entity
  oneToMany:
    children:
      targetEntity: Entity\Child
      mappedBy: parent
      indexBy: user_id # also tried with `user`
      fetch: EXTRA_LAZY

For EXTRA_LAZY neither int/string (user_id in this case) nor user (User entity) works as a key when using containsKey on collection, regardless if it's indexBy: user_id or indexBy: user.

If I do $this->children->containsKey($user) (pass User entity as key) it will stop at ArrayCollection::containsKey() with Warning: Illegal offset type in isset or empty in line:

    return isset($this->elements[$key]) || array_key_exists($key, $this->elements);

That's obvious. So if I do $this->children->containsKey($user->getId()), then in case of mapping indexBy: user_id (column name) I get:

Unrecognized field: voted_by_id

And in case of indexBy: user it fails of SqlExpressionVisitor::walkComparision with:

PersisterException: Cannot match on Entity\Child::user with a non-object value. Matching objects by id is not compatible with matching on an in-memory collection, which compares objects by reference

because it expects an object here (which can't pass because it fails earlier).

Doctrine2 version 2.5.4
PHP 7.0.6

Originally created by @dragoste on GitHub (Aug 26, 2016). I found it impossible to use `EXTRA_LAZY` mode for collection indexed by a relation (foreign key). It may be related to #3978. Let's suppose we have `Parent` class with `Parent::children` collection where `Child::user` is unique across the collection (one `Child` per `User` for each `Parent`). When we would like to index `Parent::children` by `Child::user` property (`user_id` actually), it works for standard `fetch:LAZY` mode as implemented in PR #639, which lets us to use column name instead of property name. ``` Entity\Parent: type: entity oneToMany: children: targetEntity: Entity\Child mappedBy: parent indexBy: user_id # also tried with `user` fetch: EXTRA_LAZY ``` For `EXTRA_LAZY` neither int/string (`user_id` in this case) nor `user` (`User` entity) works as a key when using `containsKey` on collection, regardless if it's `indexBy: user_id` or `indexBy: user`. If I do `$this->children->containsKey($user)` (pass `User` entity as key) it will stop at `ArrayCollection::containsKey()` with `Warning: Illegal offset type in isset or empty` in line: ``` return isset($this->elements[$key]) || array_key_exists($key, $this->elements); ``` That's obvious. So if I do `$this->children->containsKey($user->getId())`, then in case of mapping `indexBy: user_id` (column name) I get: ``` Unrecognized field: voted_by_id ``` And in case of `indexBy: user` it fails of `SqlExpressionVisitor::walkComparision` with: ``` PersisterException: Cannot match on Entity\Child::user with a non-object value. Matching objects by id is not compatible with matching on an in-memory collection, which compares objects by reference ``` because it expects an object here (which can't pass because it fails earlier). Doctrine2 version 2.5.4 PHP 7.0.6
Author
Owner

@ihor commented on GitHub (Jun 15, 2018):

Did you find a solution to this?

@ihor commented on GitHub (Jun 15, 2018): Did you find a solution to this?
Author
Owner

@dragoste commented on GitHub (Jun 15, 2018):

@ihor Nope. I tried to debug Doctrine's code and I think there's no workaround to keep both EXTRA_LAZY and indexBy: foreign_key as it's messed up in Doctrine core codebase.
Since there was no response to this issue, I finally decided to give up on EXTRA_LAZY in my case.

@dragoste commented on GitHub (Jun 15, 2018): @ihor Nope. I tried to debug Doctrine's code and I think there's no workaround to keep both `EXTRA_LAZY` and `indexBy: foreign_key` as it's messed up in Doctrine core codebase. Since there was no response to this issue, I finally decided to give up on `EXTRA_LAZY` in my case.
Author
Owner

@ajgarlag commented on GitHub (Apr 4, 2022):

Since ORM 2.11 you can expose the foreign_key (user_id) column as a virtual column and use it as the indexed field of an EXTRA_LAZY association. See https://www.doctrine-project.org/2022/01/11/orm-2.11.html

@ajgarlag commented on GitHub (Apr 4, 2022): Since ORM 2.11 you can expose the `foreign_key` (`user_id`) column as a virtual column and use it as the indexed field of an `EXTRA_LAZY` association. See https://www.doctrine-project.org/2022/01/11/orm-2.11.html
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5235