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.

5
Top

Care to rate this post?

Author

Darko Goles

Ex Inchooer

Darko worked at Inchoo as Backend Developer from March 2011 to January 2014

Other posts from this author

Discussion 5 Comments

Add Comment
  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?

  2. Paloma

    Thanks thanks a lot!!!!

  3. Windall

    Are there other solutions? Maybe direct from the Entity postUpdate Action itself?

  4. Windall

    “method: postUpdate” seems to be obsolet in tags: config

Add Your Comment

Please wrap all source codes with [code][/code] tags.
Top