1

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.

4
  • What exception message do you get when trying to submit your form? Commented Jan 24, 2014 at 1:17
  • Problem is how to clean object from related for first flush, when there is no PK/id for related. I did some dirty workaround but feel this is not right way. /**@PrePersist{ Commented Jan 24, 2014 at 3:11
  • User Entity: /**@ORM\PrePersist*/ onPrePersist{ unset($this->profile)}, and inside controller $profile=$user->getProfile(); $em->persist($user); $em->flush($user); $user->setProfile($profile); $em->flush($user) Commented Jan 24, 2014 at 3:20
  • Sorry , I updated question - Exception msg. Commented Jan 24, 2014 at 3:44

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

5 Comments

Hi. I want to keep mapping as is because that way I have UserProfile foreign key as User PK. That's not possible if I'll change owner side to User. Yes, I know about bidirectional update and I have setter set as you described. Doctrine cant insert UserProfile without id/PK and that is not possible without PK on User. Closed circle
Ok, so just add cascade={"persist"} to "user" mapping in your UserProfile, and that should help.
I had hoped this is it, but still the same exception. :/
Thank you for trying to help. I have Id. $user mapping in UserProfile has that annotation. console doctrine:schem:create creates everything perfectly, including foreign constraint. I read that part Doctrine documentation you mention, I am using annotation and Use-Case 2: Simple Derived Identity - example looks exactly like my mapping.
Oh, ok, sorry I've missed that. So as the exception stays you can't do that in this way, because primary key of the inverse side depends on primary key of the owning side. So you can 1) reverse inversed-owning sides 2) separate primary key from foreign key in UserProfile (this would be my choice) 3) flush the owning side before inversed one. I can't see any other choice, but maybe it exists - I can't say

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.