Intereting Posts
Медленная выборка содержимого из URL-адреса Как сделать Http Video Streaming PHP или сайт рефери, чтобы сделать это? В чем разница между php cli и php cgi? PHP Regex, извлеките все пользовательские теги из текста Как создать общую базу данных, макет которой может меняться со временем? Как получить loginRedirect из нескольких мест входа в CakePHP? Как я могу узнать, является ли строка с кодировкой url UTF-8 или Latin-1 с PHP? Symfony2: выбор всех переводов под родителем Получение идентификатора электронной почты отправителя при получении писем от Gmail WKHTMLTOPDF – Можно ли отображать динамические заголовки? Почему мы должны использовать статические вызовы в PHP? phpDoc и завершение кода через '->' T_OBJECT_OPERATOR в NetBeans 8.0 Почему PHP Object Operator рассматривается как закрывающий тег в браузере? Сообщение об ошибке проверки правильной формы для Codeigniter 2 Какой адрес электронной почты для использования в API аккаунта Google Service

Уязвимое расширение Doctrine 'on change' не работает

Я на Symfony 2.6.3 с расширением Doctrine.

TimeStampable и SoftDeletable работают хорошо.

Также хорошо работают «Уязвимые» и «on update»:

/** * @var User $createdBy * * @Gedmo\Blameable(on="create") * @ORM\ManyToOne(targetEntity="my\TestBundle\Entity\User") * @ORM\JoinColumn(name="createdBy", referencedColumnName="id") */ protected $createdBy; /** * @var User $updatedBy * * @Gedmo\Blameable(on="update") * @ORM\ManyToOne(targetEntity="my\TestBundle\Entity\User") * @ORM\JoinColumn(name="updatedBy", referencedColumnName="id") */ protected $updatedBy; 

Но «на смене», похоже, не работает.

 /** * @var User $deletedBy * * @Gedmo\Blameable(on="change", field="deletedAt") * @ORM\ManyToOne(targetEntity="my\UserBundle\Entity\User") * @ORM\JoinColumn(name="deletedBy", referencedColumnName="id") */ protected $deletedBy; 

У меня SoftDeletable настроен в поле «deletedAt». SoftDeletable отлично работает, но deletedBy никогда не заполняется.

Как я могу заставить его работать? Я просто хочу установить идентификатор пользователя, который удалил объект.

Проблема в том, что вы хотите обновить объект (установить пользователя), когда вы вызываете метод remove на нем.

В настоящее время не может быть идеального решения для регистрации пользователя, который удалил объект с помощью Softdeleteable + Blameable extensions.

Некоторая идея может заключаться в том, чтобы перезаписать SoftDeleteableListener ( https://github.com/Atlantic18/DoctrineExtensions/blob/master/lib/Gedmo/SoftDeleteable/SoftDeleteableListener.php ), но у меня была проблема с этим.

Мое текущее рабочее решение – использовать ресивер Entity Listener.

MyEntity.php

 /** * @ORM\EntityListeners({„Acme\MyBundle\Entity\Listener\MyEntityListener" }) */ class MyEntity { /** * @ORM\ManyToOne(targetEntity="Acme\UserBundle\Entity\User") * @ORM\JoinColumn(name="deleted_by", referencedColumnName="id") */ private $deletedBy; public function getDeletedBy() { return $this->deletedBy; } public function setDeletedBy($deletedBy) { $this->deletedBy = $deletedBy; } 

MyEntityListener.php

 use Doctrine\ORM\Event\LifecycleEventArgs; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Acme\MyBundle\Entity\MyEntity; class MyEntityListener { /** * @var TokenStorageInterface */ private $token_storage; public function __construct(TokenStorageInterface $token_storage) { $this->token_storage = $token_storage; } public function preRemove(MyEntity $myentity, LifecycleEventArgs $event) { $token = $this->token_storage->getToken(); if (null !== $token) { $entityManager = $event->getObjectManager(); $myentity->setDeletedBy($token->getUser()); $entityManager->persist($myentity); $entityManager->flush(); } } } 

Несовершенство здесь вызывает метод flush.

Регистрация службы:

 services: myentity.listener.resolver: class: Acme\MyBundle\Entity\Listener\MyEntityListener arguments: - @security.token_storage tags: - { name: doctrine.orm.entity_listener, event: preRemove } 

Обновление доктрины / доктрины в композиторе.json:

 "doctrine/doctrine-bundle": "1.3.x-dev" 

Если у вас есть другие решения, особенно если речь идет о SoftDeleteableListener, отправьте его здесь.

Здесь мое решение:

 mybundle.soft_delete: class: Listener\SoftDeleteListener arguments: - @security.token_storage tags: - { name: doctrine_mongodb.odm.event_listener, event: preSoftDelete } 
 class SoftDeleteListener { /** * @var TokenStorageInterface */ private $tokenStorage; public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } /** * Method called before "soft delete" system happened. * * @param LifecycleEventArgs $lifeCycleEvent Event details. */ public function preSoftDelete(LifecycleEventArgs $lifeCycleEvent) { $document = $lifeCycleEvent->getDocument(); if ($document instanceof SoftDeletedByInterface) { $token = $this->tokenStorage->getToken(); if (is_object($token)) { $oldValue = $document->getDeletedBy(); $user = $token->getUser(); $document->setDeletedBy($user); $uow = $lifeCycleEvent->getObjectManager()->getUnitOfWork(); $uow->propertyChanged($document, 'deletedBy', $oldValue, $user); $uow->scheduleExtraUpdate($document, array('deletedBy' => array($oldValue, $user))); } } } 

}

Это мое решение, я использую событие preSoftDelete:

 app.event.entity_delete: class: AppBundle\EventListener\EntityDeleteListener arguments: - @security.token_storage tags: - { name: doctrine.event_listener, event: preSoftDelete, connection: default } 

и обслуживание:

 <?php namespace AppBundle\EventListener; use Doctrine\ORM\Event\LifecycleEventArgs; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; class EntityDeleteListener { /** * @var TokenStorageInterface */ private $tokenStorage; public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } public function preSoftDelete(LifecycleEventArgs $args) { $token = $this->tokenStorage->getToken(); $object = $args->getEntity(); $om = $args->getEntityManager(); $uow = $om->getUnitOfWork(); if (!method_exists($object, 'setDeletedBy')) { return; } if (null == $token) { throw new AccessDeniedException('Only authorized users can delete entities'); } $meta = $om->getClassMetadata(get_class($object)); $reflProp = $meta->getReflectionProperty('deletedBy'); $oldValue = $reflProp->getValue($object); $reflProp->setValue($object, $token->getUser()->getUsername()); $om->persist($object); $uow->propertyChanged($object, 'deletedBy', $oldValue, $token->getUser()->getUsername()); $uow->scheduleExtraUpdate($object, array( 'deletedBy' => array($oldValue, $token->getUser()->getUsername()), )); } } 

Это непротиворечивость, потому что я проверяю метод setDeletedBy и устанавливаю свойство deletedBy, но он работает для меня, и вы можете обновить этот код для своих нужд

Вот еще одно решение, которое я нашел:

Зарегистрируйте услугу:

 softdeleteable.listener: class: AppBundle\EventListener\SoftDeleteableListener arguments: - '@security.token_storage' tags: - { name: doctrine.event_listener, event: preFlush, method: preFlush } 

SoftDeleteableListener:

 /** * @var TokenStorageInterface|null */ private $tokenStorage; /** * DoctrineListener constructor. * * @param TokenStorageInterface|null $tokenStorage */ public function __construct(TokenStorageInterface $tokenStorage) { $this->tokenStorage = $tokenStorage; } /** * @param PreFlushEventArgs $event */ public function preFlush(PreFlushEventArgs $event) { $user = $this->getUser(); $em = $event->getEntityManager(); foreach ($em->getUnitOfWork()->getScheduledEntityDeletions() as $object) { /** @var SoftDeleteableEntity|BlameableEntity $object */ if (method_exists($object, 'getDeletedBy') && $user instanceof User) { $object->setDeletedBy($user); $em->merge($object); // Persist and Flush allready managed by other doctrine extensions. } } } /** * @return User|void */ public function getUser() { if (!$this->tokenStorage || !$this->tokenStorage instanceof TokenStorageInterface) { throw new \LogicException('The SecurityBundle is not registered in your application.'); } $token = $this->tokenStorage->getToken(); if (!$token) { /** @noinspection PhpInconsistentReturnPointsInspection */ return; } $user = $token->getUser(); if (!$user instanceof User) { /** @noinspection PhpInconsistentReturnPointsInspection */ return; } return $user; }