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

Итак, все мои объекты унаследованы от 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;
}

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

1
Al Foиce ѫ 5 Сен 2016 в 17:29

3 ответа

Лучший ответ

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

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

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

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 }
4
Boolean_Type 7 Фев 2020 в 12:57

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

Вам необходимо создать прослушиватель событий или подписчик для прослушивания события доктрины postPersist и заполнить соответствующий атрибут. Проверьте Как зарегистрировать слушателей и подписчиков событий

1
Vadim Ashikhman 5 Сен 2016 в 14:46

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

1
Benoît 5 Сен 2016 в 15:20