gondor
gondor

Reputation: 93

Store entity from session doesn't work => $em->persist()

at first: Sorry for my poor english :-)

A beginner need help!

I have 3 entities/tables:

Tables:

contact_person
id, title, firstname, surname, adress_id

address
id, street, zip, city, country_id

country (fix values)
id, name, code
1, Austria, AT
2, Germany, DE
...

Entities:

/**
 * ContactPerson
 *
 * @ORM\Table(name="contact_person")
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class ContactPerson
{
    /**
     * @var integer $contactPersonId
     *
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $contactPersonId;

    /**
     * @ORM\Column(name="title", type="string", columnDefinition="ENUM('m', 'w')")
     */
    private $title;

    /**
     * @ORM\Column(name="firstname", type="string", length=255)
     */
    private $firstName;

    /**
     * @ORM\Column(name="surname", type="string", length=255)
     */
    private $surName;

    /**
     * @ORM\OneToOne(targetEntity="Trac\TracBundle\Entity\Address", cascade={"persist"})
     * @ORM\JoinColumn(name="address_id", referencedColumnName="id")
     */
    protected $address;

    ...
}

/**
 * Address
 *
 * @ORM\Table(name="address")
 * @ORM\Entity
 * @ORM\HasLifecycleCallbacks
 */
class Address
{
    /**
     * @var integer $addresssId
     *
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $addresssId;

    /**
     * @ORM\Column(name="street", type="string", length=255)
     */
    private $street;

    /**
     * @ORM\Column(name="zip", type="string", length=255)
     */
    private $zip;

    /**
     * @ORM\Column(name="city", type="string", length=255)
     */
    private $city;

    /**
     * @ORM\ManyToOne(targetEntity="Trac\TracBundle\Entity\Country", inversedBy="addresses", cascade={"persist"})
     * @ORM\JoinColumn(name="country_id", referencedColumnName="id", nullable=true)
     */
    private $country;

    ...
}

/**
 * Country
 *
 * @ORM\Table(name="country")
 * @ORM\Entity
 */
class Country
{
    /**
     * @var integer $countryId
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $countryId;

    /**
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @ORM\Column(name="code", type="string", length=255)
     */
    private $code;

    ...
}

1 Form:

ContactPersonType:

$builder->add('title', 'choice', array('choices'  => array('m' => 'male', 'w' => 'female')));
$builder->add('firstname', 'text');
$builder->add('surname', 'text');
$builder->add('address', new \myBundle\Form\AddressType(), array(
    'data_class' => 'myBundle\Entity\Address'
));

AddressType:

$builder->add('street', 'text');
$builder->add('zip', 'text');
$builder->add('city', 'text');
$builder->add('country', 'entity', array(
    'class' => 'myBundle\Entity\Country',
    'property' => 'name'
));

CountryType:

$builder->add('country', 'entity', array(
    'class' => 'myBundle\Entity\Country',
    'property' => 'name'
));

When i do a form-post the controller stores the request-data successfully in tables. All works fine!

ContactPersonController:

$form->handleRequest($request);
if($form->isValid()) {

    $contact_person = $form->getData();

    $em->persist($contact_person);
    $em->flush();
}

Result in tables:

contact_person
id, title, firstname, surname, adress_id
1, Mr, Ted, Tester, 1

address
id, street, zip, city, country_id
1, myStreet, 12345, Berlin, 2

country
id, name, code
1, Austria, AT
2, Germany, DE

PROBLEM:

When i store the contact person-entities in session and call $em->persist() from another controller, the country-mapping failed:

ContactPersonController (store contact person-objects into session):

$form->handleRequest($request);
$session = $request->getSession();
if($form->isValid()) {
    $contactPersons[] = $form->getData();
    //Add to session
    $session->set('contactPersons', $contactPersons);
}

AnotherController:

...

if($form->isValid()) {

    $customer = $form->getData();

    //Customer
    $em->persist($customer);
    $em->flush();

    //Get contact persons from session
    $contactPersons = $session->get('contactPersons');

    //Save contact persons to tables
    if(is_array($contactPersons) && !empty($contactPersons)) {

        foreach($contactPersons as $key => $contactPerson) {
            $em->persist($contactPerson);
            $em->flush();
        }
    }
}

...

Wrong result into tables

contact_person
id, title, firstname, surname, adress_id
1, Mr, Ted, Tester, 1

address
id, street, zip, city, country_id
1, myStreet, 12345, Berlin, 3

country
id, name, code
1, Austria, AT
2, Germany, DE
3, Germany, DE <= Create a new row... BUT WHY??? it should reference the id 2 by mapping into address (country_id)

Thans for help,

gondor

Upvotes: 1

Views: 54

Answers (1)

redbirdo
redbirdo

Reputation: 4957

When you store doctrine entities in the session they become detached from the EntityManager. You need to merge any entities which are already in the database back into the EntityManager. Something like this (checking for null where necessary):

    foreach($contactPersons as $key => $contactPerson) {
        $mergedCountry = $em->merge($contactPerson->getAddress()->getCountry());
        $contactPerson->getAddress()->setCountry($mergedCountry);
        $em->persist($contactPerson);
    }
    $em->flush();

Upvotes: 1

Related Questions