2015-02-02 2 views
6

Я нахожусь на symfony 2.6.3 с расширением доктрины stof.Доктрина виноватого расширения 'on change' не работает

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

Также наказуемый «на создание» и «на обновление» работают слишком хорошо:

/** 
* @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 никогда не заполняется.

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

ответ

1

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

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

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

Мое текущее рабочее решение - использовать ресивер приемника сущностей.

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(); 
    } 
} 

} 

несовершенством здесь звонит флеш-метод.

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

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

Обновления доктрина/Доктрина-расслоение в composer.json:

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

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

1

Вот мое решение:

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))); 
     } 
    } 
} 

}

1

Это мое решение, я использую 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 собственность, но это работает для меня, и вы можете обновить этот код для ваших нужд

0

Вот еще одно решение Я нашел:

Зарегистрировать услугу:

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; 
} 

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

  • Нет связанных вопросов^_^