{"id":1113,"date":"2015-02-18T07:21:48","date_gmt":"2015-02-18T07:21:48","guid":{"rendered":"https:\/\/intelligentbee.com\/blog\/?p=1113"},"modified":"2024-10-25T09:01:47","modified_gmt":"2024-10-25T09:01:47","slug":"symfony2-doctrine-2-entity-listeners","status":"publish","type":"post","link":"https:\/\/intelligentbee.com\/blog\/symfony2-doctrine-2-entity-listeners\/","title":{"rendered":"Symfony2: Doctrine 2 Entity Listeners"},"content":{"rendered":"<p>When working on a little more complex application is inevitable that we&#8217;ll get to the point when we need to trigger an action when something happens somewhere in our application. Quite often is the case that we need to bind our actions to an entity, like for example notify all subscribers to a blog post that the post they are following has changed.<\/p>\n<p><!--more--><\/p>\n<p>While this task can be achieved in various ways (custom event listener, doctrine listeners\/subscribers), there is a more suitable way which\u00a0provides the best performance when compared to doctrine listeners (as those will be triggered on every entity action), and much more easier to implement and maintain than a custom event with custom listener, and that is with Doctrine Entity Listener.<\/p>\n<p>This type of listener will be\u00a0invoked just to the specified entity. The best part of this is that we can register this listeners as services which allows us to inject whatever we want in them and build some really complex logic.<\/p>\n<p>And to use it is very easy, just make sure you have Doctrine ORM 2.4 and DoctrineBundle 1.3.<\/p>\n<p>This is how the service definition should look like in <code>service.yml<\/code>:<\/p>\n<pre class=\"lang:yaml decode:true \" title=\"Doctrine Entity Listener service definition\">#services.yml\r\nservices:\r\n    user_listener:\r\n        class: AcmeDemoBundleEntityListenerUserListener\r\n        arguments: [@service_container]\r\n        tags:            \r\n            - { name: doctrine.orm.entity_listener}<\/pre>\n<p>And the listener itself:<\/p>\n<pre class=\"lang:php decode:true \" title=\"Doctrine Entity Listener service\">&lt;?php\r\nnamespace AcmeDemoBundleEntityListener;\r\n\r\nuse DoctrineORMEventLifecycleEventArgs;\r\nuse AcmeDemoBundleEntityUser;\r\nuse SymfonyComponentDependencyInjectionContainer;\r\nuse DoctrineORMMapping as ORM;\r\n\r\nclass UserListener\r\n{\r\n    \r\n    protected $container;\r\n    \r\n    public function __construct(Container $container)\r\n    {\r\n        $this-&gt;container = $container;\r\n    }\r\n    \r\n    \/** @ORMPrePersist *\/\r\n    public function prePersistHandler(User $user, LifecycleEventArgs $event)\r\n    {       \r\n        \/\/ Implement your custom logic\r\n    }\r\n}<\/pre>\n<p>If you get an exception for <code>ServiceCircularReferenceException: Circular reference detected for service ...<\/code>\u00a0when you inject a certain service into your listener, then simply inject the whole container. There is a known issue, and the recommended way is to inject the whole container in this case, as this will lazy-load the service you need.<\/p>\n<p>&nbsp;<\/p>\n<p>The documentation is straight forward and doesn&#8217;t need any more details. Just follow it on <a title=\"Doctrine Entity Listener documentation\" href=\"http:\/\/symfony.com\/doc\/master\/bundles\/DoctrineBundle\/installation.html\" target=\"_blank\" rel=\"noopener\">Symfony&#8217;s<\/a> website.<\/p>\n<p>&nbsp;<\/p>\n<p>Have fun coding <img decoding=\"async\" class=\"wp-smiley\" src=\"\/\/intelligentbee.com\/blog\/wp-includes\/images\/smilies\/icon_smile.gif\" alt=\":)\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When working on a little more complex application is inevitable that we&#8217;ll get to the point when we need to [&hellip;]<\/p>\n","protected":false},"author":28,"featured_media":1167,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[82],"tags":[123,131,164,186,194,238],"yst_prominent_words":[292,310,384,434,455,568,1007,1383,1948],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/1113"}],"collection":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/users\/28"}],"replies":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/comments?post=1113"}],"version-history":[{"count":3,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/1113\/revisions"}],"predecessor-version":[{"id":133270,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/posts\/1113\/revisions\/133270"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/media\/1167"}],"wp:attachment":[{"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/media?parent=1113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/categories?post=1113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/tags?post=1113"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/intelligentbee.com\/blog\/wp-json\/wp\/v2\/yst_prominent_words?post=1113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}