-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Description
When setting data on an embedded form that has the option 'by_reference' set to false, the provided model data is cloned before being converted to norm data / view data.
I understand that it is the desirable behavior when dealing with collections, as only the Collection instance is cloned, and not its items.
When embedding a single object, the behavior seems problematic : if the form's underlying object is a Doctrine entity previously inserted in the database, cloning it will prevent Doctrine from being able to update it - it will be considered as a new entity.
Of course, I could set 'by_reference' to true but I need the actual setter to be called on the "parent" object.
A simple example : a user entity, with an optional extended profile entity. My user form type embeds the extended profile form type. I need setExtendedProfile() to be called on the user entity, so 'by_reference' needs to be set to false. However, if I use the form to update an existing user entity, the cloning operation on the extendedProfile entity will trick Doctrine into thinking that this extendedProfile entity is a new entity.
Not sure whether it is an actual bug or if I am missing something. My first idea would be to change the Form class so that it only clones \Traversable instances, and not every single object. @bschussek, if it is indeed a reasonable solution I can provide a patch along with adapted unit tests.
class User
{
/**
* @var ExtendedProfile
* @ORM\OneToOne(targetEntity="ExtendedProfile", mappedBy="user", cascade={"all"}, orphanRemoval=true)
*/
private $extendedProfile;
public function getExtendedProfile()
{
return $this->extendedProfile;
}
public function setExtendedProfile($extendedProfile)
{
// Do important stuff here
$this->extendedProfile = $extendedProfile;
}
...
}
class ExtendedProfile
{
/**
* @var User
* @ORM\OneToOne(targetEntity="User", inversedBy="extendedProfile")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
*/
private $user;
...
}
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('extendedProfile', 'extended_profile', array('by_reference' => false))
...
}
}