doctrine / doctrine/orm

Multiple Navigational Properties to the same entity with composite primary key

Open
#10,941 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
PHP
Stars
10.2k
Forks
2.5k
Avg merge
1d 10h
Merged PRs (30d)
34

Description

### Bug Report

I have two entities `EntA` & `EntB` defined as follows:

```
id1 = $id1;
$this->id2 = $id2;
}
}

#[ORM\Entity]
class EntB {
#[ORM\Id]
#[ORM\Column(length=50)]
private string $id;
#[ORM\ManyToOne(targetEntity: EntA::class)]
#[ORM\JoinColumn(name: "ref_id", referencedColumnName="id1")]
#[ORM\JoinColumn(name: "ref_id2", referencedColumnName="id2")]
private ?EntA $ref1 = null;
#[ORM\ManyToOne(targetEntity: EntA::class)]
#[ORM\JoinColumn(name: "ref_id", referencedColumnName="id1")]
#[ORM\JoinColumn(name: "ref_id2", referencedColumnName="id2")]
private ?EntA $ref2 = null;
#[ORM\ManyToOne(targetEntity: EntA::class)]
#[ORM\JoinColumn(name: "ref_id", referencedColumnName="id1")]
#[ORM\JoinColumn(name: "ref_id3", referencedColumnName="id2", nullable=true)]
private ?EntA $ref3 = null;

public function __construct(EntA $ref1, EntA $ref2, ?EntA $ref3 = null) {
$this->id = random_str();
$this->ref1 = $ref1;
$this->ref2 = $ref2;
$this->ref3 = $ref3;
}
}
```

The design is to ensure that all reference to `EntA` from `EntB` all belong under the same parent and by parent, I mean `EntA::$id1`.

| Q | A
|------------ | ------
| BC Break | no
| Version | 2.14.0

#### Summary

Whenever I instantiate `EntB` and set `EntB::$ref3` to null, doctrine sets the column `ref_id` in the `EntB` table to null thereby making the other `EntA` references to be orphans. even though columns `ref_id1`, `ref_id2` have their values intact while column `ref_id3` is null as expected.

#### Current behavior
```
EntA Table
id1: ABC, id2: 123
id1: ABC, id2: 234

EntB Table
id: aystetx, ref_id: null, ref_id1: 123, ref_id2: 234, ref_id3: null
```
#### How to reproduce
```
$ent_a_1 = new EntA("ABC", "123");
$entityManager->persist($ent_a_1);
$ent_a_2 = new EntA("ABC", "234");
$entityManager->persist($ent_a_2);

$ent_b = new EntB($ref_a_1, $ref_a_2);
$entityManager->persist($ent_b);

$entityManager->flush();
```
#### Expected behavior
```
EntA Table
id1: ABC, id2: 123
id1: ABC, id2: 234

EntB Table
id: aystetx, ref_id: ABC, ref_id1: 123, ref_id2: 234, ref_id3: null
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the EntA and EntB mappings from the issue on Doctrine ORM 2.14.0 and inspect the SQL or persisted row after flush. Trace how multiple composite-key associations are synchronized when ref3 is null. Done means ref_id remains populated for ref1 and ref2 while only the nullable ref3 column is null.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.