支付宝扫一扫付款
微信扫一扫付款
(微信为保护隐私,不显示你的昵称)
Doctrine封装了一个丰富的事件系统,当这个系统内部发生任何事情时,事件就会触发。对于你来说,这意味着你可以创建任意的服务并告诉Doctrine每当有某些动作(如prePersist
)在Doctrine内发生时,通知这些对象。这很有用,例如,每当在您的数据库中保存一个对象时,都创建一个独立的搜索索引。
Doctrine定义了两种类型的对象,来监听Doctrine事件: listeners(监听器)和 subscribers(订阅器)。 两者都是非常相似的,但监听器还是比较简单的。有关的详细信息,请参见Doctrine官网的事件系统。
Doctrine官网还解释了所有可以被监听的现存事件。
要注册一个服务作为一个事件监听器或订阅器,您只需给它标记(tag)适当的名称即可。这取决于你的用例,你可以hook(钩)一个监听器到每个DBAL连接和ORM实体管理器(ORM entity manager)里,或者只是进入一个特定的DBAL连接里,或者是所有使用此连接的实体管理器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_sqlite
memory: true
services:
my.listener:
class: AppBundle\EventListener\SearchIndexer
tags:
- { name: doctrine.event_listener, event: postPersist }
my.listener2:
class: AppBundle\EventListener\SearchIndexer2
tags:
- { name: doctrine.event_listener, event: postPersist, connection: default }
my.subscriber:
class: AppBundle\EventListener\SearchIndexerSubscriber
tags:
- { name: doctrine.event_subscriber, connection: default } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:doctrine="http://symfony.com/schema/dic/doctrine">
<doctrine:config>
<doctrine:dbal default-connection="default">
<doctrine:connection driver="pdo_sqlite" memory="true" />
</doctrine:dbal>
</doctrine:config>
<services>
<service id="my.listener" class="AppBundle\EventListener\SearchIndexer">
<tag name="doctrine.event_listener" event="postPersist" />
</service>
<service id="my.listener2" class="AppBundle\EventListener\SearchIndexer2">
<tag name="doctrine.event_listener" event="postPersist" connection="default" />
</service>
<service id="my.subscriber" class="AppBundle\EventListener\SearchIndexerSubscriber">
<tag name="doctrine.event_subscriber" connection="default" />
</service>
</services>
</container> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | use Symfony\Component\DependencyInjection\Definition;
$container->loadFromExtension('doctrine', array(
'dbal' => array(
'default_connection' => 'default',
'connections' => array(
'default' => array(
'driver' => 'pdo_sqlite',
'memory' => true,
),
),
),
));
$container
->setDefinition(
'my.listener',
new Definition('AppBundle\EventListener\SearchIndexer')
)
->addTag('doctrine.event_listener', array('event' => 'postPersist'))
;
$container
->setDefinition(
'my.listener2',
new Definition('AppBundle\EventListener\SearchIndexer2')
)
->addTag('doctrine.event_listener', array('event' => 'postPersist', 'connection' => 'default'))
;
$container
->setDefinition(
'my.subscriber',
new Definition('AppBundle\EventListener\SearchIndexerSubscriber')
)
->addTag('doctrine.event_subscriber', array('connection' => 'default'))
; |
在前面的例子中,一个my.listener
服务被配置为一个postPersist
事件的Doctrine监听器。在服务类必须有一个postpersist
方法,当事件被派遣时,它被调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // src/AppBundle/EventListener/SearchIndexer.php
namespace AppBundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use AppBundle\Entity\Product;
class SearchIndexer
{
public function postPersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// only act on some "Product" entity
if (!$entity instanceof Product) {
return;
}
$entityManager = $args->getEntityManager();
// ... do something with the Product
}
} |
在每个事件中,你可以访问一个LifecycleEventArgs
对象,通过它你可以访问事件的实体对象和实体管理器本身。
要注意的一个重要的事情是,一个监听器将监听你应用程序中的所有实体。因此,如果你有兴趣只处理一个特定类型的实体(例如,一个Product
实体但不是一个BlogPost
实体),您应该在方法中检查实体类的类型(如上所示)。
在Doctrine2.4中,一个被称为实体监听器的功能被引入。它是一个用于实体的生命周期监听器类。你可以在Doctrine文档中读到它。
一个Doctrine事件订阅器一定要实现Doctrine\Common\EventSubscriber
接口并对于每一个订阅的事件都得有一个事件方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // src/AppBundle/EventListener/SearchIndexerSubscriber.php
namespace AppBundle\EventListener;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
// for Doctrine 2.4: Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use AppBundle\Entity\Product;
class SearchIndexerSubscriber implements EventSubscriber
{
public function getSubscribedEvents()
{
return array(
'postPersist',
'postUpdate',
);
}
public function postUpdate(LifecycleEventArgs $args)
{
$this->index($args);
}
public function postPersist(LifecycleEventArgs $args)
{
$this->index($args);
}
public function index(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// perhaps you only want to act on some "Product" entity
if ($entity instanceof Product) {
$entityManager = $args->getEntityManager();
// ... do something with the Product
}
}
} |
Doctrine 事件订阅器不可以像 Symfony 事件订阅那样返回一系列灵活的方法来调用事件。Doctrine事件订阅器必须返回一个简单数组,里面是他们订阅的事件名称。Doctrine 期待每个订阅事件和订阅器方法使用相同的名称,就像使用事件监听器一样。
想要一个完整的参考,请看Doctrine文档的事件系统。
本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。