EventListener & FOSUserBundle (fosuserbundleのリレーション)


symfony2でユーザ認証のためのバンドルFOSUserBundleが一般的になりましたが、このFOSUserBundleを使って他のBundleやEntityにリレーションしたりすることが必要になります。当たり前ですね。その時にこのリレーションをLifeCycleEventを使って自動化します。

具体的には下記の手順です。

  • 1.FOSUserBundleを導入(ここでは割愛)
  • 2.PageBundle(仮)のようにFOSUserBundleをリレーションさせたいバンドルの作成(ここでは割愛)
  • 3.Entity, LifeCycleEventをPageBundle(仮)などに組み込む(service.ymlでコントロールします)
  • 4.LifeCycleEventの実装(下記ではApp/ContentBundle/EventListener/ControllerListener.phpで実装)

FOSUserBundleをリレーションさせるEntityには

/**
* @ORM\ManyToOne(targetEntity="App\UserBundle\Entity\User")
*/
protected $createdUser;
/**
 * Set createdUser
 *
 * @param App\UserBundle\Entity\User $createdUser
 * @return Page
 */
public function setCreatedUser(\App\UserBundle\Entity\User $createdUser = null)
{
    $this->createdUser = $createdUser;

    return $this;
}
/**
 * Get createdUser
 *
 * @return App\UserBundle\Entity\User 
 */
public function getCreatedUser()
{
    return $this->createdUser;
}

としてEntityにcreatedUserを追加します。その他、createdAtやupdatedAtも追加しておけば自動で下記のLifeCycleEventはカラムを更新してくれます。

LifeCycleEventの動作をservices.yml(.xml)指定します。

App/ContentBundle/Resources/config/services.yml

parameters:
services:
    app_content.event.listener:
        class: App\ContentBundle\EventListener\ControllerListener
        arguments: ["@service_container"]
        tags:
            - { name: doctrine.event_listener, event: prePersist }
            - { name: doctrine.event_listener, event: preUpdate }
            - { name: doctrine.event_listener, event: postPersist }
            - { name: doctrine.event_listener, event: postUpdate }
            - { name: doctrine.event_listener, event: preRemove }
            - { name: doctrine.event_listener, event: postRemove }
            - { name: doctrine.event_listener, event: postLoad }

最後にControllerListener.phpとして実装します。

App/ContentBundle/EventListener/ControllerListener.php

<?php

namespace App\ContentBundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerInterface;

class ControllerListener
{
    protected $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }
    public function prePersist(LifecycleEventArgs $args)
    {
        
        $entity = $args->getEntity();
        
        if (property_exists($entity, 'createdUser')) {
            $user = $this->container->get('security.context')->getToken()->getUser();
            $entity->setCreatedUser($user);
        }
        if (property_exists($entity, 'createdAt')) {
            $entity->setCreatedAt(new \DateTime());
        }
        if (property_exists($entity, 'updatedAt')) {
            $entity->setUpdatedAt(new \DateTime());
        }
    }
    public function preUpdate(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $em = $args->getEntityManager();

        $recompute = false;

        if (property_exists($entity, 'updatedAt'))
        {
            $entity->setUpdatedAt(new \DateTime());
            $recompute = true;
        }
        if (property_exists($entity, 'updatedUser'))
        {
            $user = $this->container->get('security.context')->getToken()->getUser();
            $entity->setUpdatedUser($user);
            $recompute = true;
        }
        if ($recompute)
        {
            $meta = $em->getClassMetadata(get_class($entity));
            $em->getUnitOfWork()->recomputeSingleEntityChangeSet($meta, $entity);
        }
    }
    public function postPersist(LifecycleEventArgs $args){}
    public function postUpdate(LifecycleEventArgs $args){}
    public function postRemove(LifecycleEventArgs $args){}    
    public function preRemove(LifecycleEventArgs $args){}
    public function postLoad(LifecycleEventArgs $args){}
    
}
  • このエントリーをはてなブックマークに追加

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です