Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine - Get old value in onFlush event listener

I'm trying to implement a feature that let's the user specify his mutual status and select a another user, just like that one in Facebook.

My database schema is like:

UserInfo entity:

class UserInfo
{

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="user_info")
     */
    protected $user;

    /**
     * @ORM\Column(type="text", nullable=true)
     * @Assert\NotBlank
     */
    protected $status; //Value taken from a dropdown list

    /**
     * @ORM\OneToOne(targetEntity="User", inversedBy="relationship_with_table")
     */
    protected $relationship_user;
}

User entity:

class User
{

    /**
    * @ORM\OneToOne(targetEntity="UserInfo", mappedBy ="user", cascade={"persist","remove"})
    */
    protected $user_info;

    /**
     * @ORM\OneToOne(targetEntity="UserInfo", mappedBy="relationship_user")
     */
    protected $relationship_with_table;
}

UserInfoType :

class UserInfoType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $option)
    {
        $builder
            ->add("birthday", "birthday")
            ->add("gender", "choice", array("choices" => array("0" => "Male", "1" => "Female")))
            ->add("status", "choice", array("choices" => array(
                    "Single" => "Single",
                    "In relationship" => "In relationship",
                    "Engaged" => "Engaged",
                    "Married" => "Married"
                )))
            ->add("relationship_user", "thrace_select2_entity", array(
                    "class" => 'Zgh\FEBundle\Entity\User',
                    'label' => 'User',
                    'empty_value' => 'Select user',
                    "configs" => array(
                        "width" => '100%',
                    ),
                ))
            ->add("city", "text")
            ->add("work", "text")
            ->add("facebook", "url")
            ->add("twitter", "url")
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
                "data_class" => 'Zgh\FEBundle\Entity\UserInfo',
                "cascade_validation" => true,
            ));
    }

    public function getName()
    {
        return "user_info";
    }
}

Now here's the event listener, It checks the user status and change the other user one, It works as expected. But only has one flaw, If the user is married to (A) and then changed it to married to (B), The user (A) still gets the Married to and don't get reset.

All what i want to do is before attaching user relationship to (B), I want to retrieve (A) and reset it. How can this be done inside onFlush event.

class DoctrinePreUpdateHandler implements EventSubscriber
{
    public function getSubscribedEvents()
    {
        return array(
            "onFlush",
        );
    }

    public function onFlush(OnFlushEventArgs $args)
    {
        $em = $args->getEntityManager();
        $uow = $em->getUnitOfWork();

        $updates = $uow->getScheduledEntityUpdates();

        foreach ($updates as $entity) {

            if($entity instanceof UserInfo){

                $target_user_info = null;

                if($entity->getStatus() == "Single"){
                    if($entity->getRelationshipUser() != null){
                        $target_user_info = $entity->getRelationshipUser()->getUserInfo();
                        $target_user_info->setStatus("Single");
                        $target_user_info->setRelationshipUser(null);
                    }
                    $entity->setRelationshipUser(null);
                } else {
                    $target_user_info = $entity->getRelationshipUser()->getUserInfo();
                    $target_user_info->setStatus($entity->getStatus());
                    $target_user_info->setRelationshipUser($entity->getUser());
                }

                if($target_user_info != null){
                    $em->persist($target_user_info);
                    $uow->computeChangeSet($em->getClassMetadata(get_class($target_user_info)), $target_user_info);
                }
            }
        }
    }
}
like image 440
Rafael Adel Avatar asked May 12 '14 09:05

Rafael Adel


1 Answers

Doctrine UoW has a method propertyChanged(...) that tracks changes to entity properties. These changes are stored in the entityChangeSets-Property of the UoW.

I think it should be possible to call $uow->getEntityChangeSet($entity) which returns an array where keys are $entity's properties and values are [$oldValue, $newValue].

I'm not sure if you have to call computeChangeSet() for the old relationship user, but i hope you can figure this out and leave a comment?

like image 168
Markus Avatar answered Oct 27 '22 00:10

Markus