d3uter
d3uter

Reputation: 767

Symfony2 Doctrine insert entity with related - NOT UPDATE

I have problem with inserting User entity with related entity UserProfile.

class User
{
/**
 * @var integer
 *
 * @ORM\Id
 * @ORM\Column(name="id", type="integer",  options={"unsigned"=true})
 * @ORM\GeneratedValue(strategy="AUTO")
 */
protected $id;

/**
 * @var UserProfile
 *
 * @ORM\OneToOne(targetEntity="UserProfile", mappedBy="user", cascade={"persist", "remove"})
 */
protected $profile
....
}


class UserProfile
{
/**
 * @var User
 *
 * @ORM\Id
 * @ORM\GeneratedValue
 * @ORM\OneToOne(targetEntity="User",  inversedBy="profile" )
 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
 */
protected $user;
.....
}

Standard User-UserProfile bidirectional relation. When I submit form contains fields from User entity and UserProfile entity, $form->getData() gives me User object with UserProfile. So far so good.

Mysql generate a unique identity by auto-increment PK. To insert entity I have to do:

$em->persist($user)
$em->flush() 

to get PK as id for persist and flush UserProfile.

But doctrine CANT insert $user because $user object has related $user->profile received from form Type:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
     ->add('email', 'email', array('label' => 'email'))
     ->add('profile', new RegistrationProfileFormType(), array('required'=>true,))
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'User',
        'cascade_validation'=>true,
    ));
}

Update: Exception msg Entity of type Entity\UserProfile has identity through a foreign entity Entity\User, however this entity has no identity itself. You have to call EntityManager#persist() on the related entity and make sure that an identifier was generated before trying to persist 'Entity\UserProfile'. In case of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call EntityManager#flush() between both persist operations.

Q: How to handle this problem properly ?

Sorry for my rusty English.

Upvotes: 1

Views: 4058

Answers (1)

Cyprian
Cyprian

Reputation: 11364

The problem is you are going to perist objects through not owning side. Owning side is the one with "inversedBy" property. And you should persist objects that way.

You can read more about it here: http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html

So, example for your case:

$profile->setUser($user);
$em->persist($profile).
$em->flush();

Although, if you want to keep the way you already have, there are two options:

1) Make User entity as the owning side and UserProfile as the inverse side

or

2) In your profile setter in User class do something like that:

public function setUserProfile(UserProfile $profile)
{
    $this->profile = $profile;
    $this->profile->setUser($this);
}

edit:

I've just notice that you don't have "id" field in your UserProfile entity - probably this is the reason. the easiest way would be separate primary and foreign keys. But if you want treat foreign as primary take a look at this article: http://docs.doctrine-project.org/en/latest/tutorials/composite-primary-keys.html#identity-through-foreign-entities

Upvotes: 1

Related Questions