chuber50 chuber50 - 1 month ago 37
PHP Question

Disable Doctrine 2 lazy loading when using JMS Serializer?

Im using Doctrine 2 ORM in my Zend project and need to serialize my Entities to JSON in several cases.

ATM i use the Querybuilder and join all tables i need. But my serializer causes doctrine to lazy load every associated Entity which results in pretty huge data amounts and provokes recursion.

Now im looking for a way to totally disable Doctrines lazy loading behavior.

My way to select data would be the following:

$qb= $this->_em->createQueryBuilder()
->from("\Project\Entity\Personappointment", 'pa')
->select('pa', 't', 'c', 'a', 'aps', 'apt', 'p')
->leftjoin('pa.table', 't')
->leftjoin('pa.company', 'c')
->leftjoin('pa.appointment', 'a')
->leftjoin('a.appointmentstatus', 'aps')
->leftjoin('a.appointmenttype', 'apt')
->leftjoin('a.person','p')


I would like my resultset to only contain the selected tables and associations.

Any help would be greatly appreciated.

Answer

After having looked for the answer in Doctrine, my team figured out that the JMS Serializer was the "problem". It triggered the use of Doctrine Proxies automatically. We wrote a Patch for JMS Serializer to avoid the Lazy Loading.

We implemented our own DoctrineProxyHandler which just doesn't trigger Doctrines lazyloading mechanism and registered it within our SerializationHandlers Array.

class DoctrineProxyHandler implements SerializationHandlerInterface {

public function serialize(VisitorInterface $visitor, $data, $type, &$handled)
{
    if (($data instanceof Proxy || $data instanceof ORMProxy) && (!$data->__isInitialized__ || get_class($data) === $type)) {
        $handled = true;

        if (!$data->__isInitialized__) {

            //don't trigger doctrine lazy loading
            //$data->__load();

            return null;
        }

        $navigator = $visitor->getNavigator();
        $navigator->detachObject($data);

        // pass the parent class not to load the metadata for the proxy class
        return $navigator->accept($data, get_parent_class($data), $visitor);
    }

    return null;
}

Now i can simply select my table, join the associations i need - and my JSON will contain just the data i selected instead of infinite depth associations and recursions :)

$qb= $this->_em->createQueryBuilder()
        ->from("\Project\Entity\Personappointment", 'pa')
        ->select('pa', 't', 'c', 'a')
        ->leftjoin('pa.table', 't')
        ->leftjoin('pa.company', 'c')
        ->leftjoin('pa.appointment', 'a')

JSON will just contain

{  
  Personappointment: { table {fields}, company {fields}, appointment {fields}}
  Personappointment: { table {fields}, company {fields}, appointment {fields}}
  Personappointment: { table {fields}, company {fields}, appointment {fields}}
  .
  .
}
Comments