在Symfony2项目中,我使用了Loggable Doctrine Extension。
我saw有一个LoggableListener。
当可记录实体中的(可记录)字段发生更改时,确实会触发事件吗?如果是这样,有没有办法获得触发它的字段列表?
我想象一个实体的情况,让我们说10个字段,其中3个可记录。对于3中的每一个,如果他们改变了值,我想要执行一些操作,因此如果3个操作发生变化,将执行3个操作。
有什么想法吗?
谢谢!
修改
在阅读下面的评论并阅读有关学说的事件的文档后,我了解了3个选项:
1)如果我使用doctrine> 2.4
,则直接在实体级lifecycle callbacks使用with arguments 2)我可以listen and subscribe to Lifecycle Events,但在这种情况下,文档会说"Lifecycle events are triggered for all entities. It is the responsibility of the listeners and subscribers to check if the entity is of a type it wants to handle."
3)做你的建议,即使用Entity listener,你可以在实体层面定义哪个是将被附加的""上课。
即使第一个解决方案看起来更容易,我也会读到"您也可以使用此监听器来实现已更改的所有字段的验证。当使用昂贵的验证来调用"时,这比使用生命周期回调更有效。什么被认为是一种昂贵的验证?"。
在我的情况下,我必须执行的操作类似于"如果实体Y的字段X发生了变化,则在通知表上添加通知说"用户Z从A更改了X(Y)的值到B"
考虑到我有大约1000个像这样的字段,哪种方法最合适?
EDIT2
为了解决我的问题,我试图在监听器中注入service_container服务,这样我就可以访问调度程序来调度一个新事件,该事件可以执行我需要的新实体的持久化。但是我该怎么做呢?
我尝试了常用的方法,我将以下内容添加到service.yml
app_bundle.project_tolereances_listener:
class: AppBundle\EventListener\ProjectTolerancesListener
arguments: [@service_container]
当然我向听众添加了以下内容:
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
但我得到以下内容:
Catchable Fatal Error: Argument 1 passed to AppBundle\ProjectEntityListener\ProjectTolerancesListener::__construct() must be an instance of AppBundle\ProjectEntityListener\ContainerInterface, none given, called in D:\provarepos\user\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\DefaultEntityListenerResolver.php on line 73 and defined
有什么想法吗?
答案 0 :(得分:5)
Loggable侦听器仅保存实体的监视属性的更改值。
它不会触发事件,它会侦听onFlush
和postPersist
学说事件。
我认为您正在寻找preUpdate和prePersist事件上的Doctrine监听器,您可以在flush
之前操作变更集。
请参阅:http://doctrine-orm.readthedocs.org/en/latest/reference/events.html
如果您使用的是Doctrine 2.4+,可以轻松地将它们添加到您的实体中:
简单的实体类:
namespace Your\Namespace\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\EntityListeners({"Your\Namespace\Listener\DogListener"})
*/
class Dog
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=100)
*/
private $name;
/**
* @ORM\Column(type="integer")
*/
private $age;
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* @return int
*/
public function getAge()
{
return $this->age;
}
/**
* @param int $age
*/
public function setAge($age)
{
$this->age = $age;
}
}
然后在Your\Namespace\Listener
中创建ListenerClass DogListener
:
namespace Your\Namespace\Listener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Your\Namespace\Entity\Dog;
class DogListener
{
public function preUpdate(Dog $dog, PreUpdateEventArgs $event)
{
if ($event->hasChangedField('name')) {
$updatedName = $event->getNewValue('name'). ' the dog';
$dog->setName($updatedName);
}
if ($event->hasChangedField('age')) {
$updatedAge = $event->getNewValue('age') % 2;
$dog->setAge($updatedAge);
}
}
public function prePersist(Dog $dog, LifecycleEventArgs $event)
{
//
}
}
清除缓存并在刷新时调用侦听器。
你是正确的recomputeSingleEntityChangeSet在这种情况下不需要。我更新了监听器的代码。
第一种选择(实体内方法)的问题是您无法在方法中注入其他服务。 如果您只需要EntityManager,那么是,这是代码最简单的方法。
使用外部Listener类,您可以这样做。
如果这1000个字段位于多个单独的实体中,则第二种类型的监听器将是最合适的。您可以创建一个包含所有观看/通知逻辑的NotifyOnXUpdateListener
。
要在EntityListener中注入服务,请将Listener声明为标记为doctrine.orm.entity_listener
的服务,并注入所需内容。
<service id="app.entity_listener.your_service" class="Your\Namespace\Listener\SomeEntityListener">
<argument type="service" id="logger" />
<argument type="service" id="event_dispatcher" />
<tag name="doctrine.orm.entity_listener" />
</service>
并且监听器将如下所示:
class SomeEntityListener
{
private $logger;
private $dispatcher;
public function __construct(LoggerInterface $logger, EventDispatcherInterface $dispatcher)
{
$this->logger = $logger;
$this->dispatcher = $dispatcher;
}
public function preUpdate(Block $block, PreUpdateEventArgs $event)
{
//
}
}
根据:How to use Doctrine Entity Listener with Symfony 2.4?,它需要DoctrineBundle 1.3 +