2012-05-18 126 views
2

我已經註冊了以下監聽器作爲服務。這保存了登錄用戶。它完美的作品。保存實體後,用戶標識位於createdBy和updatedBy中。好的一個小問題:命令「php app/console doctrine:fixtures:load」會拋出錯誤「調用一個非對象的成員函數getUser()。 這是可以理解的。只有現在,我必須禁用每一個時間之前的服務呢?當你調用命令負載燈具你有另一種解決方案?Symfony2監聽器和DataFixtures

 
class UserListener implements EventSubscriber 
{ 
    protected $container; 

    public function __construct(ContainerInterface $container) 
    { 
     $this->container = $container; 
    } 

    public function getSubscribedEvents() 
    { 
     return array(
      Events::prePersist, 
      Events::preUpdate 
     ); 
    } 

    public function prePersist(LifecycleEventArgs $args) 
    { 
     $entity = $args->getEntity(); 

     if ($entity instanceof Post) { 

      $user = $this->container->get('security.context')->getToken()->getUser(); 

      if (!is_object($user) || !$user instanceof User) { 
       throw new AccessDeniedException(); 
      } 

      $entity->setCreatedBy($user); 
      $entity->setUpdatedBy($user); 
     } 
    } 

    /** 
    * @param PreUpdateEventArgs $args 
    */ 
    public function preUpdate(PreUpdateEventArgs $args) 
    { 
     $entity = $args->getEntity(); 

     $em = $args->getEntityManager(); 

     if ($entity instanceof Post) { 

      $user = $this->container->get('security.context')->getToken()->getUser(); 

      if (!is_object($user) || !$user instanceof User) { 
       throw new AccessDeniedException(); 
      } 

      $entity->setUpdatedBy($user); 

      $uow = $em->getUnitOfWork(); 
      $meta = $em->getClassMetadata(get_class($entity)); 
      $uow->recomputeSingleEntityChangeSet($meta, $entity); 
     } 
    } 
} 

回答

1

,您還沒有登錄。也許$this->container->get('security.context')->getToken()返回null?

+1

問題解決了與prePersist PHP_SAPI條件。 – stwe

+0

你能發佈最終的代碼@stwe嗎? – webDEVILopers

+0

順便說一句,使用'$ this-> container-> get('security.authorization_checker')'代替(2.6中的new) – Ronan

0

我也有類似的監聽器,並且是試圖保存一個(模擬)實體(在你的案例中爲「Post」)。當然,我從控制檯啓動命令時沒有登錄。

我加了一個條件,聽者:

if ($entity instanceof Post) { 
    if (null !== $entity->getUser() { 
     return; 
    } 
} 

現在我可以設置在後實體(模擬)用戶我的燈具內:

$user = $em->getReference('Application\Sonata\UserBundle\Entity\User', 1); 
$post = new Post(); 
$post->setUser($user); 

仍不確定是否設置用戶內實體監聽器是很好的做法。

我想目前大多數人會推薦使用ValueObject作爲「Post」或者至少需要設置一個構造函數,例如,一個「名字」和一個「用戶」。

0

我的最終代碼(Symfony的2.6):

1)監聽器:

<?php 

namespace AppBundle\Listener; 

use AppBundle\Entity\Post; 
use AppBundle\Entity\Comment; 

use Doctrine\ORM\Event\LifecycleEventArgs; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; 

/** 
* Class BlameableListener 
* 
* @package AppBundle\Listener 
*/ 
class BlameableListener 
{ 
    private $tokenStorage; 

    public function __construct(TokenStorageInterface $tokenStorage) 
    { 
     $this->tokenStorage = $tokenStorage; 
    } 

    public function prePersist(LifeCycleEventArgs $args) 
    { 
     $entity = $args->getEntity(); 

     if ($entity instanceof Post || $entity instanceof Comment) { 
      // is authentication information available? 
      if (null !== $this->tokenStorage->getToken()) { 
       // get User 
       $user = $this->tokenStorage->getToken()->getUser(); 
       if (is_object($user)) { 
        $entity->setAuthorEmail($user->getEmail()); 
       } 
      } 
     } 
    } 
} 

2)配置作爲服務

services: 
    app.blameable.listener: 
     class: AppBundle\Listener\BlameableListener 
     arguments: 
      - "@security.token_storage" 
     tags: 
      - { name: doctrine.event_listener, event: prePersist }