[doctrine/symfony] automatisch relaties leggen bij opslaan?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 11-09 20:35
De topictitel is misschien niet heel erg duidelijk maar ik wist niet goed hoe ik het moest verwoorden. Ik ben bezig met het opzetten van een applicatie die gebruik maakt van symfony 2 en doctrine 2.

Wat vaak voorkomt is dat een entiteit een lijst heeft waarin andere entiteiten staan (one-to-many relatie).
In het onderstaande voorbeeld heeft een persoon meerdere adressen en elk adres hoort maar bij 1 persoon.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person
{
    ....
    
    /**
     * @ORM\OneToMany(targetEntity="Address", mappedBy="person", cascade={"persist"})
     */
    protected $addressList;
    
    ....
}

class Address
{
    ....
    
    /**
     * @ORM\ManyToOne(targetEntity="Person", inversedBy="addressList")
     * @ORM\JoinColumn(name="person_id", referencedColumnName="id")
     */
    protected $person;
    
    ....
}


Wat ik nu graag zou willen is dat een adres automatisch wordt aangemaakt wanneer een persoon opgeslagen wordt. Met de cascade optie in de annotation wordt een adres wel opgeslagen, maar wanneer er in het adres zelf nog geen relatie is gelegd naar de persoon wordt deze relatie niet door doctrine gelegd, person_id blijft dus leeg (NULL).

Voorbeeld:
PHP:
1
2
3
4
5
6
7
$person = new Person(..);
$entityManager->persist($person);

$address = new Address(..);
$person->addAddress($address);

$entityManager->flush();


In het bovenstaande voorbeeld wordt het adres dus wel opgeslagen, maar in het adres zelf wordt niet de relatie met de persoon gelegd. In het onderstaande voorbeeld wordt de relatie wel goed gelegd maar dan moet ik dus zowel de persoon als het adres individueel opslaan in de database en dat is niet wat ik wil. Doe ik iets fout of begrijp ik de documentatie van doctrine over cascade opties niet goed?
PHP:
1
2
3
4
5
6
7
8
9
$person = new Person(..);
$entityManager->persist($person);
$entityManager->flush();


$address = new Address(..);
$address->setPerson($person);
$entityManager->persist($address);
$entityManager->flush();


Edit:
Als ik het andersom doe, dus de cascade persist in de Person entity zet, en aan elk adres de nieuwe person koppel werkt het wel. Maar voor mijn gevoel is dit verkeerd om, als ik een persoon met tien adressen wil aanmaken, dan maak ik het persoon object met de tien adressen en wil ik alleen de persoon opslaan met de lijst van adressen, niet alle adressen.

Edit2:
Een oplossing zou zijn om bij de functie addAddress() in Person de instantie van Person toe te wijzen aan het adres. Dit werkt en is misschien ook wel logisch. Toch vraag ik me af of doctrine die relatie niet automatisch kan leggen?

[ Voor 11% gewijzigd door IceM op 01-05-2012 08:07 ]

...


Acties:
  • 0 Henk 'm!

  • IceM
  • Registratie: Juni 2003
  • Laatst online: 11-09 20:35
Bump ... iemand?

...


Acties:
  • 0 Henk 'm!

  • MichelVH
  • Registratie: Oktober 2001
  • Laatst online: 11-09 21:04
De cascade persist is puur om te zorgen dat een persist() call op je root object ook de onderliggende objecten oppakt indien er objecten toegevoegd/gewijzigd/verwijderd zijn. Je moet je persist() call ook pas uitvoeren op het moment dat het object 'compleet' is, dus na calls op addAddress().

Zoals je in de documentatie kunt lezen, ben je zelf verantwoordelijk voor het beheren van relaties.

Je code wordt dan bijvoorbeeld:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Person
{

    public function addAddress(Address $address) {
        $this->addressList[] = $address;
        $address->setPerson($this);
    }

}

class Address
{
}

$address = new Address(..);

$person = new Person(..);
$person->addAddress($address);

$entityManager->persist($person);
$entityManager->flush();

Probeer je entiteiten los te zien van Doctrine. Zorg eerst dat je entiteiten 'logisch' werken zonder Doctrine (dus bijv. zodra je een object toevoegt aan een relatie, dat ook de relatie de andere kant op klopt). Doctrine verzorgt dan puur de mapping van je entiteiten in je database :)

Don't be afraid of the dark, be afraid of what it hides