概述 快速入门 教程 手册 最佳实践 组件 参考 贡献

发布于 2015-08-27 16:39:32 | 203 次阅读 | 评论: 0 | 来源: 网络整理

Doctrine packages a rich event system that fires events when almost anything happens inside the system. For you, this means that you can create arbitrary services and tell Doctrine to notify those objects whenever a certain action (e.g. prePersist) happens within Doctrine. This could be useful, for example, to create an independent search index whenever an object in your database is saved.

Doctrine defines two types of objects that can listen to Doctrine events: listeners and subscribers. Both are very similar, but listeners are a bit more straightforward. For more, see The Event System on Doctrine’s website.

The Doctrine website also explains all existing events that can be listened to.

Configuring the Listener/Subscriber

To register a service to act as an event listener or subscriber you just have to tag it with the appropriate name. Depending on your use-case, you can hook a listener into every DBAL connection and ORM entity manager or just into one specific DBAL connection and all the entity managers that use this connection.

  • YAML
    doctrine:
        dbal:
            default_connection: default
            connections:
                default:
                    driver: pdo_sqlite
                    memory: true
    
    services:
        my.listener:
            class: AcmeSearchBundleEventListenerSearchIndexer
            tags:
                - { name: doctrine.event_listener, event: postPersist }
        my.listener2:
            class: AcmeSearchBundleEventListenerSearchIndexer2
            tags:
                - { name: doctrine.event_listener, event: postPersist, connection: default }
        my.subscriber:
            class: AcmeSearchBundleEventListenerSearchIndexerSubscriber
            tags:
                - { name: doctrine.event_subscriber, connection: default }
    
  • XML
    <?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="AcmeSearchBundleEventListenerSearchIndexer">
                <tag name="doctrine.event_listener" event="postPersist" />
            </service>
            <service id="my.listener2" class="AcmeSearchBundleEventListenerSearchIndexer2">
                <tag name="doctrine.event_listener" event="postPersist" connection="default" />
            </service>
            <service id="my.subscriber" class="AcmeSearchBundleEventListenerSearchIndexerSubscriber">
                <tag name="doctrine.event_subscriber" connection="default" />
            </service>
        </services>
    </container>
    
  • PHP
    use SymfonyComponentDependencyInjectionDefinition;
    
    $container->loadFromExtension('doctrine', array(
        'dbal' => array(
            'default_connection' => 'default',
            'connections' => array(
                'default' => array(
                    'driver' => 'pdo_sqlite',
                    'memory' => true,
                ),
            ),
        ),
    ));
    
    $container
        ->setDefinition(
            'my.listener',
            new Definition('AcmeSearchBundleEventListenerSearchIndexer')
        )
        ->addTag('doctrine.event_listener', array('event' => 'postPersist'))
    ;
    $container
        ->setDefinition(
            'my.listener2',
            new Definition('AcmeSearchBundleEventListenerSearchIndexer2')
        )
        ->addTag('doctrine.event_listener', array('event' => 'postPersist', 'connection' => 'default'))
    ;
    $container
        ->setDefinition(
            'my.subscriber',
            new Definition('AcmeSearchBundleEventListenerSearchIndexerSubscriber')
        )
        ->addTag('doctrine.event_subscriber', array('connection' => 'default'))
    ;
    

Creating the Listener Class

In the previous example, a service my.listener was configured as a Doctrine listener on the event postPersist. The class behind that service must have a postPersist method, which will be called when the event is dispatched:

// src/Acme/SearchBundle/EventListener/SearchIndexer.php
namespace AcmeSearchBundleEventListener;

use DoctrineORMEventLifecycleEventArgs;
use AcmeStoreBundleEntityProduct;

class SearchIndexer
{
    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        // perhaps you only want to act on some "Product" entity
        if ($entity instanceof Product) {
            // ... do something with the Product
        }
    }
}

In each event, you have access to a LifecycleEventArgs object, which gives you access to both the entity object of the event and the entity manager itself.

One important thing to notice is that a listener will be listening for all entities in your application. So, if you’re interested in only handling a specific type of entity (e.g. a Product entity but not a BlogPost entity), you should check for the entity’s class type in your method (as shown above).

小技巧

In Doctrine 2.4, a feature called Entity Listeners was introduced. It is a lifecycle listener class used for an entity. You can read about it in the Doctrine Documentation.

Creating the Subscriber Class

A Doctrine event subscriber must implement the DoctrineCommonEventSubscriber interface and have an event method for each event it subscribes to:

// src/Acme/SearchBundle/EventListener/SearchIndexerSubscriber.php
namespace AcmeSearchBundleEventListener;

use DoctrineCommonEventSubscriber;
use DoctrineORMEventLifecycleEventArgs;
// for Doctrine 2.4: DoctrineCommonPersistenceEventLifecycleEventArgs;
use AcmeStoreBundleEntityProduct;

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();
        $entityManager = $args->getEntityManager();

        // perhaps you only want to act on some "Product" entity
        if ($entity instanceof Product) {
            // ... do something with the Product
        }
    }
}

小技巧

Doctrine event subscribers can not return a flexible array of methods to call for the events like the Symfony event subscriber can. Doctrine event subscribers must return a simple array of the event names they subscribe to. Doctrine will then expect methods on the subscriber with the same name as each subscribed event, just as when using an event listener.

For a full reference, see chapter The Event System in the Doctrine documentation.

最新网友评论  共有(0)条评论 发布评论 返回顶部

Copyright © 2007-2017 PHPERZ.COM All Rights Reserved   冀ICP备14009818号  版权声明  广告服务