[Bug] Relation can't be changed if you fetch an entity and also a collection of its related entities #5961

Closed
opened 2026-01-22 15:23:11 +01:00 by admin · 9 comments
Owner

Originally created by @grongor on GitHub (May 3, 2018).

Hello,

if I fetch an entity with its collection initialized (like eager fetch but in one query), like so:

$entityManager->createQueryBuilder()
    ->select('c, s')
    ->from(Customer::class, 'c')
    ->leftJoin('c.servers', 's')
    ->getQuery()
    ->getSingleResult();

and then I try to change the relation (change server's customer to a different one or set it to null), then it doesn't work - ORM generates an empty transaction.

I created a repo with a minimalistic example of this behavior: https://github.com/grongor/doctrine-bug-tmp

You can run it yourself, but for your convenience, I already provided output and the diff between the two tests.

Originally created by @grongor on GitHub (May 3, 2018). Hello, if I fetch an entity with its collection initialized (like eager fetch but in one query), like so: ``` $entityManager->createQueryBuilder() ->select('c, s') ->from(Customer::class, 'c') ->leftJoin('c.servers', 's') ->getQuery() ->getSingleResult(); ``` and then I try to change the relation (change server's customer to a different one or set it to `null`), then it doesn't work - ORM generates an empty transaction. I created a repo with a minimalistic example of this behavior: https://github.com/grongor/doctrine-bug-tmp You can run it yourself, but for your convenience, I already provided output and the diff between the two tests.
admin added the Bug label 2026-01-22 15:23:11 +01:00
admin closed this issue 2026-01-22 15:23:11 +01:00
Author
Owner

@Ocramius commented on GitHub (May 8, 2018):

What's the failing assertion in your code? Also: can it be ported to the ORM test suite?

@Ocramius commented on GitHub (May 8, 2018): What's the failing assertion in your code? Also: can it be ported to the ORM test suite?
Author
Owner

@grongor commented on GitHub (May 8, 2018):

Well, it's a proof of the bug :D I assert that the results from the query are the same as the state of entities before flush(). The assert fails because flush() doesn't persist the state as it should.

I'll look into moving it to the ORM test suite.

@grongor commented on GitHub (May 8, 2018): Well, it's a proof of the bug :D I assert that the results from the query are the same as the state of entities before `flush()`. The assert fails because `flush()` doesn't persist the state as it should. I'll look into moving it to the ORM test suite.
Author
Owner

@Ocramius commented on GitHub (May 8, 2018):

Well, it's a proof of the bug :D

I was asking which assertion specifically failed in the example code (the first failure).

Still, having the failure in the ORM test suite would allow us to fiddle around with the issue. See https://github.com/doctrine/doctrine2/tree/master/tests/Doctrine/Tests/ORM/Functional/Ticket for examples.

@Ocramius commented on GitHub (May 8, 2018): > Well, it's a proof of the bug :D I was asking which assertion specifically failed in the example code (the first failure). Still, having the failure in the ORM test suite would allow us to fiddle around with the issue. See https://github.com/doctrine/doctrine2/tree/master/tests/Doctrine/Tests/ORM/Functional/Ticket for examples.
Author
Owner

@grongor commented on GitHub (May 8, 2018):

Sorry, I didn't catch that ... code with the bug is testNotWorking.php and in its output testNotWorking__output.txt you can see which assert it is and on which line - it's the last one (asserting that actual data in the database are as expected, after flush().

And yeah, I will look into moving it to the ORM test suite :) This was a quick hack, at first to only minimize the code.

@grongor commented on GitHub (May 8, 2018): Sorry, I didn't catch that ... code with the bug is `testNotWorking.php` and in its output `testNotWorking__output.txt` you can see which assert it is and on which line - it's the last one (asserting that actual data in the database are as expected, after `flush()`. And yeah, I will look into moving it to the ORM test suite :) This was a quick hack, at first to only minimize the code.
Author
Owner

@Ocramius commented on GitHub (May 8, 2018):

Hmm, that assertion seems to be wrong:

4f423df143/src/testNotWorking.php (L37-L46)

Also, DBAL does not support PDO::FETCH_KEY_PAIR, so maybe that's where the misunderstanding is.

@Ocramius commented on GitHub (May 8, 2018): Hmm, that assertion seems to be wrong: https://github.com/grongor/doctrine-bug-tmp/blob/4f423df143a3df693b44be4d37d7b8f8202d4a82/src/testNotWorking.php#L37-L46 Also, DBAL does not support `PDO::FETCH_KEY_PAIR`, so maybe that's where the misunderstanding is.
Author
Owner

@grongor commented on GitHub (May 8, 2018):

What seems wrong with it? I don't see anything bad there ...

Also PDO:FETCH_KEY_PAIR works quite well even though it's not supported.

Anyway, I updated the code and removed it. It didn't have any effect whatsoever - the bug is still there. You can check it here: 448a80a4d8

I will look into ORM test suite asap (I have my hands full atm, sorry).

@grongor commented on GitHub (May 8, 2018): What seems wrong with it? I don't see anything bad there ... Also `PDO:FETCH_KEY_PAIR` works quite well even though it's not supported. Anyway, I updated the code and removed it. It didn't have any effect whatsoever - the bug is still there. You can check it here: https://github.com/grongor/doctrine-bug-tmp/commit/448a80a4d857b8b8280b4df40b0b07c1588d859f I will look into ORM test suite asap (I have my hands full atm, sorry).
Author
Owner

@grongor commented on GitHub (May 8, 2018):

Ok so here is the PR with the test case: https://github.com/doctrine/doctrine2/pull/7217

I found out two thigs:

  1. It works on master, branches 2.6 and 2.7 fail (test case is written in a way that you can simple cherry-pick to test it)
  2. It's caused by the combination of indexBy="id" in
/**
 * @OneToMany(targetEntity=GH7212Child::class, mappedBy="parent", indexBy="id")
 * @var GH7212Child[]|Collection
 */
protected $children;

and selection of multiple entities and left-joining them in

$parent = $this->entityManager->createQueryBuilder()
    ->select('p, c')
    ->from(GH7212Parent::class, 'p')
    ->leftJoin('p.children', 'c')
    ->getQuery()
    ->getSingleResult();

If you remove either one then the test case won't fail.

@grongor commented on GitHub (May 8, 2018): Ok so here is the PR with the test case: https://github.com/doctrine/doctrine2/pull/7217 I found out two thigs: 1. It works on master, branches 2.6 and 2.7 fail (test case is written in a way that you can simple cherry-pick to test it) 2. It's caused by the combination of `indexBy="id"` in ``` /** * @OneToMany(targetEntity=GH7212Child::class, mappedBy="parent", indexBy="id") * @var GH7212Child[]|Collection */ protected $children; ``` and selection of multiple entities and left-joining them in ``` $parent = $this->entityManager->createQueryBuilder() ->select('p, c') ->from(GH7212Parent::class, 'p') ->leftJoin('p.children', 'c') ->getQuery() ->getSingleResult(); ``` If you remove either one then the test case won't fail.
Author
Owner

@Ocramius commented on GitHub (May 8, 2018):

Aha, I didn't see the indexBy at all.

@Ocramius commented on GitHub (May 8, 2018): Aha, I didn't see the `indexBy` at all.
Author
Owner

@grongor commented on GitHub (May 8, 2018):

Yeah, and I didn't think it was related at all (to be honest, I kinda forgotten about it :D ) until I somehow stumbled over it and noticed that it is part of the problem :D

@grongor commented on GitHub (May 8, 2018): Yeah, and I didn't think it was related at all (to be honest, I kinda forgotten about it :D ) until I somehow stumbled over it and noticed that it is part of the problem :D
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5961