Ij heb een hoop geneste entities die ik wil mergen met de entity manager, maar ik krijg een "ContextErrorException" als een bepaalde property (entity collection) één of meer items bevat:
Hier is een dump van het object dat ik probeer te mergen:
Dit is de ORM mapping voor de entities:
Ik heb alle andere properties van "Card" weggelaten aangezien het probleem enkel lijkt voor te komen bij de "energies" property van "cardAttack" (zoals te zien in de stack trace; "CardAttackEnergy" heeft een composite key bestaande uit "CardAttack" en "EnergyType").
Het probleem lijkt ook enkel voor te komen indien "CardAttackEnergy" verwijst naar een een nog niet bestaande "CardAttack". Is dit waar de "undefined index: id" vandaan komt (aangezien cardAttack->id === null)? Zouden de cascade merge opties niet eerst "CardAttack" moeten persisten en pas vervolgens "CardAttackEnergy" indien deze niet bestaan?
code:
1
2
3
4
5
| Symfony\Component\Debug\Exception\ContextErrorException: Notice: Undefined index: id at vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php:97 at Doctrine\ORM\Utility\IdentifierFlattener-> flattenIdentifier(object(ClassMetadata), array()) (vendor/doctrine/orm/lib/Doctrine/ORM/Utility/IdentifierFlattener.php:84) at Doctrine\ORM\Utility\IdentifierFlattener-> flattenIdentifier(object(ClassMetadata), array('attack' => object(CardAttack), 'type' => object(EnergyType))) (vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1838) |
Hier is een dump van het object dat ik probeer te mergen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| Card {#1124 ▼ -id: null -attacks: ArrayCollection {#1225 ▼ -elements: array:1 [▼ 0 => CardAttack {#1227 ▼ -id: null -card: Card {#1124} -name: "22323" -energies: ArrayCollection {#1540 ▼ -elements: array:2 [▼ 0 => CardAttackEnergy {#1217 ▼ -attack: CardAttack {#1227} -type: EnergyType {#1536 ▼ -id: 1 -name: "Colorless" -symbolFilePath: "content/energy-type-symbols/colorless.png" } -amount: 1 } 1 => CardAttackEnergy {#1538 ▼ -attack: CardAttack {#1227} -type: EnergyType {#1539 ▼ -id: 3 -name: "Dragon" -symbolFilePath: "content/energy-type-symbols/dragon.png" } -amount: 1 } ] } -damage: "2" -description: null } ] } } |
Dit is de ORM mapping voor de entities:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
| /** * @ORM\Entity(repositoryClass="AppBundle\Repository\CardRepository") * @ORM\Table(name="card") */ class Card { /** * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @AccessType("public_method") * * @Assert\Valid() * * @ORM\OneToMany( * targetEntity="\AppBundle\Entity\CardAttack", * mappedBy="card", * cascade="all", * orphanRemoval=true * ) * @ORM\OrderBy({"id"="ASC"}) */ private $attacks; } /** * @ORM\Entity * @ORM\Table(name="card_attack") */ class CardAttack { /** * @ORM\Id * @ORM\Column(name="id", type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @Assert\NotBlank() * @Assert\Type("\AppBundle\Entity\Card") * @Assert\Valid() * * @ORM\ManyToOne(targetEntity="\AppBundle\Entity\Card", inversedBy="attacks") * @ORM\JoinColumn(name="card_id", referencedColumnName="id") */ private $card; /** * @Assert\NotBlank() * @Assert\Type(type="string") * @Assert\Length(max=50) * * @ORM\Column(name="name", type="string", length=50) */ private $name; /** * @AccessType("public_method") * * @Assert\Valid() * @CustomAssert\UniqueCollectionEntity(field="type") * * @ORM\OneToMany( * targetEntity="\AppBundle\Entity\CardAttackEnergy", * mappedBy="attack", * cascade="all", * orphanRemoval=true * ) */ private $energies; /** * @Assert\Type(type="string") * @Assert\Length(max=5) * * @ORM\Column(name="damage", type="string", length=5) */ private $damage; /** * @Assert\Type(type="string") * * @ORM\Column(name="description", type="text") */ private $description; } /** * @ORM\Entity * @ORM\Table(name="card_attack_has_energy") */ class CardAttackEnergy { /** * @Assert\NotBlank() * @Assert\Type("\AppBundle\Entity\CardAttack") * @Assert\Valid() * * @ORM\Id * @ORM\ManyToOne(targetEntity="\AppBundle\Entity\CardAttack", inversedBy="energies") * @ORM\JoinColumn(name="card_attack_id", referencedColumnName="id") */ private $attack; /** * @Assert\NotBlank() * @Assert\Type("\AppBundle\Entity\EnergyType") * @Assert\Valid() * * @ORM\Id * @ORM\ManyToOne(targetEntity="\AppBundle\Entity\EnergyType", cascade="merge") * @ORM\JoinColumn(name="energy_type_id", referencedColumnName="id") */ private $type; /** * @Assert\NotBlank() * @Assert\Type(type="integer") * @Assert\Range(min=1, max=10) * * @ORM\Column(name="amount", type="integer") */ private $amount; } |
Ik heb alle andere properties van "Card" weggelaten aangezien het probleem enkel lijkt voor te komen bij de "energies" property van "cardAttack" (zoals te zien in de stack trace; "CardAttackEnergy" heeft een composite key bestaande uit "CardAttack" en "EnergyType").
Het probleem lijkt ook enkel voor te komen indien "CardAttackEnergy" verwijst naar een een nog niet bestaande "CardAttack". Is dit waar de "undefined index: id" vandaan komt (aangezien cardAttack->id === null)? Zouden de cascade merge opties niet eerst "CardAttack" moeten persisten en pas vervolgens "CardAttackEnergy" indien deze niet bestaan?