symfony - preUpdate() siblings manage into tree: how to break ->persist() recursion? -


let's i've got entity this

class fooentity {   $id;    //foreign key fooentity   $parent_id;    //if no parent level =1, if have parent without parent = 2 , on...   $level;    //sorting index relative level   $sorting_index } 

now on delete , on edit change level , sorting_index of entity.

so i've decided take advantage of doctrine2 entitylisteners , i've done similar to

class foolistener {   public function preupdate(foo $entity, lifecycleeventargs $args)     {         $em = $args->getentitymanager();         $this->handleentityordering($entity, $em);     }      public function preremove(foo $entity, lifecycleeventargs $args)     {         $level = $entity->getlevel();         $cur_sorting_index = $entity->getsortingindex();         $em = $args->getentitymanager();         $this->handlesiblingordering($level, $cur_sorting_index, $em);     }      private function handleentityordering($entity, $em)     {         error_log('entity to_update_category stop flag: '.$entity->getstopeventpropagationstatus());         error_log('entity splobj: '.spl_object_hash($entity));         //code calculate new sorting_index , level entity (omitted)         $this->handlesiblingordering($old_level, $old_sorting_index, $em);         }     }      private function handlesiblingordering($level, $cur_sorting_index, $em)     {            $to_update_foos = //retrieve db siblings needs update         //some code update sibling ordering (omitted)         foreach ($to_update_foos $to_update_foo)         {             $em->persist($to_update_foo);         }         $em->flush();     } } 

the problem here pretty clear: if persist foo entity, preupdate() (into handlesiblingordering function) trigger raised , cause infinite loop.

my first idea insert special variable inside entity prevent loop: when started sibling update, variable setted , before executing update code checked. works charm preremove() not preupdate().
if notice i'm logging spl_obj_hash understand behaviour. big surprise can see obj passed preupdate() after preremove() same (so setting "status flag" fine) object passed preupdate() after preupdate() isn't same.

so ...

first question

someone point me in right direction manage situation?

second question

why doctrine needs generate different objects if 2 similar events raised?

i've founded workaround

best approach problem seem create custom eventsubscriber custom event dispatched programmatically controller update action.
way can "break" loop , having working code.

just make answer complete report snippet of code clarify che concept

create custom events bundle

//src/path/to/your/bundle/yourbundlenameevents.php  final class yourbundlenameevents {     const foo_event_update = 'bundle_name.foo.update'; } 

this special class not provide custom events our bundle

create custom event foo update

//src/path/to/your/bundle/event/fooupdateevent class fooupdateevent {   //this class dispatched add properties useful own logic. in example 2 properties $level , $sorting_index. values setted before dispatch event } 

create custom event subscriber

//src/path/to/your/bundle/eventlistener/foosubscriber class foosubscriber implements eventsubscriberinterface {     public static function getsubscribedevents()     {         return array(yourbundlenameevents::fooupdate => 'handlesiblingsordering');     }      public function handlesiblingsordering(fooupdateevent $event)     {         //i can retrieve there, $event, data setted event itself. can run own logic code re-order siblings     } } 

register subscriber service

//app/config/config.yml  services: your_bundlename.foo_listener:         class: your\bundle\name\eventlistener\foolistener         tags:             - { name: kernel.event_subscriber } 

create , dispatch events controller

//src/path/to/your/bundle/controller/foocontroller class foocontroller extends controller {     public function updateaction()     {         //some code here         $dispatcher = $this->get('event_dispatcher');         $foo_event = new fooevent();         $foo_event->setlevel($level); //just example         $foo_event->setorderingindex($ordering_index); //just examle          $dispatcher->dispatch(yourbundlenameevents::fooupdate, $foo_event);     } } 

alternative solution

of course above solution best 1 but, if have property mapped db used flag, access directly lifecycleeventargs of preupdate() event calling

$event->getnewvalue('flag_name'); //$event object of lifecycleeventargs type 

by using flag check changes , stop propagation


Comments

Popular posts from this blog

Email notification in google apps script -

c++ - Difference between pre and post decrement in recursive function argument -

javascript - IE11 incompatibility with jQuery's 'readonly'? -