Symfony2 registering Doctrine Event Listeners

Featured Image © by alaasafei/sxc.hu

Handling for example status change inside one entity and automatic updating status on another entity is not so trivial task. We should be aware of possible status combinations depending of actions taken. I just have three statuses for each entity: Item and ItemRepository and following article solves only one part of problem.
This time I had to make some changes on item relations right after item entity is updated.
Easier way I found is to register event listener for postUpdate on Item entity and prePersist on ItemsToCollections entity.
First of all, I created entry in my config.yml file like this:

#..

services:
  my.listener:
        class: Surgeworks\CoreBundle\Listener\ItemsStatusUpdater
        tags:
            - { name: doctrine.event_listener, event: postUpdate, method: postUpdate }
            - { name: doctrine.event_listener, event: prePersist, method: prePersist }
 
#...

After that I created ItemStatusUpdater class like this where all logic are implemented:

<?php
 
namespace Surgeworks\CoreBundle\Listener;
 
use Doctrine\ORM\Event\LifecycleEventArgs;
 
class ItemsStatusUpdater {
 
    public function postUpdate(LifecycleEventArgs $args) {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();
 
        if ($entity instanceof \Surgeworks\CoreBundle\Entity\Item) {
 
            $params = array('item_id' => $entity->getId());
            $col_repo = $entityManager->getRepository('Surgeworks\CoreBundle\Entity\ItemsToCollections');
 
            $status_id = $entity->getStatusId();
 
            $q = $entityManager->createQuery("SELECT s.status_symbol FROM Surgeworks\CoreBundle\Entity\Status s WHERE s.id = $status_id");
 
            $res = $q->getResult();
 
            if (isset($res[0]['status_symbol'])) {
 
                if ($res[0]['status_symbol'] != 'st_live') {
 
                    $col = $col_repo->findBy($params);
 
                    foreach ($col as $c) {
                        $c->setStatusId($entity->getStatusId());
                        $entityManager->persist($c);
                        $col_repo->setStatusToAllChilds($c->getPathWithId(), $entity->getStatusId());
                    }
                }
            }
            $entityManager->flush();
        }
    }
 
    public function prePersist(LifecycleEventArgs $args) {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();
        if ($entity instanceof \Surgeworks\CoreBundle\Entity\ItemsToCollections) {
 
            $item_id = $entity->getItemId();
            $item = $entityManager->getRepository('Surgeworks\CoreBundle\Entity\Item')->find($item_id);
            $stat_symb = $item->getItemStatus()->getStatusSymbol();
 
            if ($stat_symb != 'st_live') {
                $entity->setStatusId($item->getStatusId());
            }
        }
    }
 
}

In the code you see I had to filter the entity types on which Doctrine2 actions was taken and then handle changes to update dependent entities.

That way I handled automatically status changing for items and items2collections entities depending on each other.

Interested in hiring us?

Have a chat with us. You would be surprised how small changes can make your business even more successful.


5 comments

  1. Hi! Thanks for the post. It seems very easy to implement, but I’m wondering if there is way to attach the events to just one entity instead of the whole doctrine?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.