symfonydoctrinesymfony-2.4foselasticabundle

Symfony2 FOSElasticaBundle update index for all entities related to the entity updated


I'm using FOSElasticaBundle and Doctrine in my project, and my code works for the selective index update using the Doctrine lifecycle events. The issue I come up against is if I an update a related entity separately.

For example a person may be related to a company through a manytomany relationship. If I update the company name through company entity directly, then indexes for the person related to the company will be out of date and still relate to the company's old name.

I'm a bit lost as to how to handle this, does anyone have any suggestions? Do I have to rely on a scheduled index update and cope with inaccurate index data in the mean time, or is there a way I can call an update for entities related to the entity that has been updated.

I am relying on JMSSerializer groups to establish the mappings. I appreciate this might not be the best way to do things in the longterm.


Solution

  • I think I've found the solution on this page https://groups.google.com/forum/#!topic/elastica-php-client/WTONX-zBTI4 Thanks Cassiano

    Basically you need to extend the FOS\ElasticaBundle\Doctrine\ORM\Listener so you can look for related entities and then update their index as well.

    class CompanyListener extends BaseListener
    {
    
        /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
        private $container;
    
        public function setContainer(\Symfony\Component\DependencyInjection\ContainerInterface $container) {
            $this->container = $container;
        }
    
        protected function initialiseJob() {
            $this->objectPersisterJob = $this->container->get('fos_elastica.object_persister.application.job');
            $this->em = $this->container->get('doctrine')->getEntityManager(); //maybe move this to postUpdate function so it can be used for all
        }
    
        /**
         * @param \Doctrine\ORM\Event\LifecycleEventArgs $eventArgs
         */
        public function postUpdate(LifecycleEventArgs $eventArgs)
        {
            /** @var $entity Story */
            $entity = $eventArgs->getEntity();
    
            if ($entity instanceof $this->objectClass) {
                if ($this->isObjectIndexable($entity)) {
                    $this->objectPersister->replaceOne($entity);
                    $this->initialiseJob();
                    foreach ($entity->getJobOpenings() as $job) {
                        $this->objectPersisterJob->replaceOne($job);
                    }
                } else {
                    $this->scheduleForRemoval($entity, $eventArgs->getEntityManager());
                    $this->removeIfScheduled($entity);
                }
            }
        }
    
        public function preRemove(\Doctrine\Common\EventArgs $eventArgs)
        {
            $entity = $eventArgs->getEntity();
    
            if ($entity instanceof $this->objectClass) {
    
                $this->scheduleForDeletion($entity);
                $this->initialiseJob();
                foreach ($entity->getJobOpenings() as $job) {
                    $this->objectPersisterJob->replaceOne($job);
                }
            }
        }
    
    
    }
    

    and your services defined as below

    fos_elastica.listener.application.company:
        class: 'xxx\RMSBundle\EventListener\CompanyListener'
        arguments:
            - '@fos_elastica.object_persister.application.company'
            - 'xxx\RMSBundle\Entity\Company'
            - ['postPersist', 'postUpdate', 'postRemove', 'preRemove']
            - id
        calls:
            - [ setContainer, [ '@service_container' ] ]
        tags:
            - { name: 'doctrine.event_subscriber' }
    

    this will then update indexes for both :-)