2016-09-05 2 views
1

В приложении Symfony2.8/Doctrine2 мне нужно хранить в каждой строке таблицы SQL идентификатор пользователя, который создал или обновил строку (пользователи могут подключаться к Ldap).Symfony получает идентификатор пользователя от объекта

Так что все мои объекты, унаследованные из GenericEntity, содержащих эти переменных (типа будет строкой, если я хочу, чтобы хранить Ldap имя пользователя):

/** 
* @var integer 
* 
* @ORM\Column(name="zzCreationId", type="string", nullable=false) 
*/ 
private $creationId; 

И я использую prePersistCallback() автоматически присвою это значение:

/** 
* @ORM\PrePersist 
*/ 
public function prePersistCallback() 
{ 
    $currentUser = /* ...... ????? ....... */ ; 
    if ($currentUser->getId() != null) { 
     $this->creationId = $currentUser->getId() ; 
    } else { 
     $this->creationId = 'unknown' ; 
    } 
    return $this; 
} 

Но я не знаю, как восстановить подключенного пользователя или как автоматически вставить его в объект ... Как я могу это сделать?

+0

Вы должны добавить связь между вами. Пользовательский объект и ваш GenericEntity. – DOZ

+0

@DOZ. Мои пользователи подключены через Ldap, мне нужно отыскать его из контекста безопасности. Но как ? –

ответ

3

Вы можете использовать Doctrine объект прослушивателя/абонент вместо этого и вводить маркер безопасности и получает текущий пользователь, вошедший:

// src/AppBundle/EventListener/EntityListener.php 
namespace AppBundle\EventListener; 

use Doctrine\ORM\Event\LifecycleEventArgs; 
use AppBundle\Entity\GenericEntity; 

class EntityListener 
{ 
    private $tokenStorage; 

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

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

     // only act on some "GenericEntity" entity 
     if (!$entity instanceof GenericEntity) { 
      return; 
     } 

     if (null !== $currentUser = $this->getUser()) { 
      $entity->setCreationId($currentUser->getId()); 
     } else { 
      $entity->setCreationId(0); 
     } 
    } 

    public function getUser() 
    { 
     if (!$this->tokenStorage) { 
      throw new \LogicException('The SecurityBundle is not registered in your application.'); 
     } 

     if (null === $token = $this->tokenStorage->getToken()) { 
      return; 
     } 

     if (!is_object($user = $token->getUser())) { 
      // e.g. anonymous authentication 
      return; 
     } 

     return $user; 
    } 
} 

Следующая зарегистрирует вас слушатель:

# app/config/services.yml 
services: 
    my.listener: 
     class: AppBundle\EventListener\EntityListener 
     arguments: ['@security.token_storage'] 
     tags: 
      - { name: doctrine.event_listener, event: prePersist } 
+0

Ваше решение кажется самым близким мне. Я попытался реализовать его, но, к сожалению, мое поле 'creationId', унаследованное от' GenericEntity', которое является 'MappedSuperclass', отсутствует в моем дочернем Entity, и событие запускается только с моим дочерним объектом без' MappedSuperclass' поля. Таким образом, PrePersist не имеет никакого эффекта. Обратите внимание: если я использую PrePersistCallback в моем GenericEntity, поля существуют ... –

+0

Неплохо, я обновил свой ответ с помощью setter, это должно быть в вашем дочернем объекте. Однако не стесняйтесь изменять целевую сущность. – yceruto

+0

Все в порядке с сеттерами, спасибо большое! –

1

@ORM\PrePersist и другие методы обратного вызова, используемые в сущности, предполагают содержать простую логику и быть независимыми от других служб.

Чтобы прослушать событие postPersist, необходимо создать прослушиватель событий или заполнить соответствующий атрибут. Проверить How to Register Event Listeners and Subscribers

1

Вы можете посмотрите на BlameableListener из пакета gedmo/doctrine-extensions, которые работают практически так, как вы хотите, но с именем пользователя, а не с идентификатором пользователя.

Смежные вопросы