Search code examples
phpsymfony-3.4sonata

Pass the returned value of a function as a property to json using EventSubscriber


I've built an api using JMS serialize bundle. Moreover, I have an entity Ticket, which has a repository called TicketRepository. This repository contains the following method:

/**
 * @param Ticket $object
 *
 * @return string
 */
public function findByTicketDeadline($object)
{
  // some logic
}

My goal: Pass The returned value of this function to json using EventSubscriber.

Here is my class TicketSerializationSubscriber

 class TicketSerializationSubscriber implements EventSubscriberInterface
{


    /**
     * @param ObjectEvent $event
     */
    public function onPostSerialize(ObjectEvent $event)
    {
        /** @var JsonSerializationVisitor $visitor */
        $visitor = $event->getVisitor();
        $visitor->setData('ticketDeadline', 'TEST TICKET'); // WORKS

        /** @var Ticket $ticket */
        $ticket = $event->getObject();
        /** @var TicketRepository $ticketRepo */
        $ticketRepo = $event->getObject();

        $visitor->setData('TESTING', $ticketRepo->findByTicketDeadline($ticket));

//        $visitor->setData('uri',
//                $this->router->generate('ticket_api_show', [
//                    'ticketDeadline' => $ticketRepo->findByTicketDeadline($ticket)
//                ])
//        );

    }

    public static function getSubscribedEvents()
    {
        return array(
            array(
                'event' => 'serializer.post_serialize',
                'method' => 'onPostSerialize',
                'class' => 'CMS3\CoreBundle\Entity\Ticket', // if no class, subscribe to every serialization
                //'class' => 'CMS3\CoreBundle\Repository\TicketRepository', // if no class, subscribe to every serialization
                'format' => 'json', // optional format
                //'priority' => 0, // optional priority
            ),
        );
    }

}

When I passed the repository method to $visitor->setData() function, I get this error: enter image description here


Solution

  • Your current code is failing because $ticketRepo = $event->getObject(); is returning the Ticket object as in the line above it, not the expected TicketRepository.

    You will need to inject the EntityManager or Repository (if you have repositories as a service) into your TicketSerializationSubscriber::__construct() to retrieve the TicketRepository.

    Assuming you have autowire enabled for the directory containing TicketSerializationSubscriber.

    use Doctrine\ORM\EntityManagerInterface;
    
    class TicketSerializationSubscriber implements EventSubscriberInterface
    {
        /**
         * @var \Doctrine\ORM\EntityManager
         */
        private $em;
    
        public function __construct(EntityManagerInterface $em)
        {
             $this->em = $em;
        }
    
        public function onPostSerialize(ObjectEvent $event)
        {
            /** @var JsonSerializationVisitor $visitor */
            $visitor = $event->getVisitor();
    
            $ticket = $event->getObject();
            if (!$ticket instanceof Ticket) {
                //ensure object is of expected type
                return;
            }
    
            /** @var TicketRepository $ticketRepo */
            $ticketRepo = $this->em->getRepository(Ticket::class);
    
            $visitor->setData('TESTING', $ticketRepo->findByTicketDeadline($ticket));
            //...
        }
    
        //...
    
    }
    

    If not using autowire you will need to manually add it to your TicketSerializationSubscriber service declaration arguments.

    #app/config/services.yml
    
    services:
        #...
    
        TicketSerializationSubscriber:
            public: false
            arguments: ['@doctrine.orm.entity_manager']
            tags:
                - { name: kernel.event_subscriber }
                #...
    

    Be sure to clear and warmup the Symfony cache after making the changes.