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){} }