Как я могу получить текущего пользователя в мои классы сущностей? - PullRequest
2 голосов
/ 09 января 2020

Я занимаюсь разработкой своего первого Symfony 4 приложения и перехожу с Symfony 2+ и symfony 3 +.

. Сейчас я занимаюсь разработкой серверной части и всех своих классов сущностей. у меня есть методы addedBy() и updatedBy(), где мне нужно записать текущий зарегистрированный администратор.

Я хотел бы иметь что-то вроде прослушивателя событий, где мне не нужно устанавливать эти методы во всех моих контроллеры.

Как сделать sh это?

Ответы [ 2 ]

1 голос
/ 09 января 2020

Вы, вероятно, не хотите изобретать велосипед. Существует Blameable Doctrine Extension , который уже делает это. Вы можете установить его с помощью:

composer require antishov/doctrine-extensions-bundle

Поскольку рецепт для его настройки уже существует. Затем вы можете активировать расширение , а затем использовать его с чем-то вроде:

Specifi c документацию для расширения Blameable можно найти здесь

use Gedmo\Mapping\Annotation as Gedmo;

class Post {

  /**
  * @var User $createdBy
  *
  * @Gedmo\Blameable(on="create")
  * @ORM\ManyToOne(targetEntity="App\Entity\User")
  */
  private $createdBy;

}
1 голос
/ 09 января 2020

Во-первых, чтобы упростить дело и помочь в будущем, я бы создал интерфейс, которому должны соответствовать объекты, отслеживающие пользователей:

interface UserTracking
{
    public function addedBy(UserInterface $user);
    public function updatedby(UserInterface $user);
    public function getAddedBy(): ?UserInterface;
    public function getUpdatedBy(): ?UserInterface;
}

Затем вы можете создать Doctrine прослушиватель событий и добавьте туда компонент Security:

class UserDataListener 
{
    protected $security;

    public function __construct(Security $security)
    {
        $this->security = $security;
    }

    public function prePersist(LifecycleEventArgs $event): void
    {
        $entity =  $event->getObject();
        $user   = $this->security->getUser();

        // only do stuff if $entity cares about user data and we have a logged in user
        if ( ! $entity instanceof UserTracking || null === $user ) {
            return;
        }

        $this->setUserData($entity, $user);
    }

    private function preUpdate(LifecycleEventArgs $event) {
        $this->prePersist($event);
    } 

    private function setUserData(UserTracking $entity, UserInterface $user)
    {

        if (null === $entity->getAddedBy()) {
            $entity->addedBy($user);
        }

        $entity->updatedBy($user);
    }
}    

Вам нужно соответствующим образом пометить слушателя, чтобы он срабатывал на prePersist и preUpdate:

services:
  user_data_listener:
    class: App\Infrastructure\Doctrine\Listener\UserDataListener
    tags:
      - { name: doctrine.event_listener, event: prePersist }
      - { name: doctrine.event_listener, event: preUpdate }

Хотя вышеприведенное должно работать, Я полагаю, что вообще не очень хорошая идея использовать Doctrine события таким образом , так как вы связываете логи своего домена c с Doctrine и скрываете изменения под слоем волхвов c, который может быть неочевидным для других разработчиков, работающих с вашим приложением.

Я бы поставил createdBy в качестве параметра конструктора и установил бы updateBy явно при необходимости. Это просто одна строка кода каждый раз, но вы получаете ясность и выразительность, и у вас есть более простая система с меньшим количеством движущихся частей.

class FooEntity
{    
    private $addedBy;
    private $updatedBy;
    public function __construct(UserInterface $user)
    {
        $this->addedBy = $user;
    }

    public function updatedBy(UserInterface $user)
    {
        $this->updatedBy = $user;
    }
}

Это намного лучше отражает то, что происходит с доменом, и будущие кодеры в вашему приложению не нужно искать возможные расширения, которые вы, возможно, установили и активировали, или какие события запускаются.

...