Search code examples
symfonyserializationentitytranslation

Serialize translateble entity


For translate my entity product use next code

use Knp\DoctrineBehaviors\Model as ORMBehaviors;
class Product
{
    /**
     * @Groups({"prod_translate"})
     */
    use ORMBehaviors\Translatable\Translatable;
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @Groups({"prod"})
     */
    private $id;
...

Translatable create new entity ProductTranslation with table in DB product_translation with id, translatable_id, locale and translatble properties. Translation work perfectly. In page just write {{ product.translation.en/sp.name }} When use ajax pagenation use serializer for return data. Tried JMS\Serializer\SerializerBuilder and Symfony\Component\Serializer\Serializer

    use Symfony\Component\Serializer\Serializer;
    use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
    use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
    use Doctrine\Common\Annotations\AnnotationReader;
$products = $em->getRepository('AppBundle:Product')->findNextPageByBrandCategoryIds( array($cat), $brand, $offset, $limit );

    $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
            $normalizer = new ObjectNormalizer($classMetadataFactory);
            $normalizer->setCircularReferenceHandler(function ($object) {
                return $object->getID();
            });
            $serializer = new Serializer(array($normalizer));
            $jsonObject = $serializer->normalize($products, 'json', array('groups' => array('prod', 'prod_translate')) );

Without groups serializet return "Maximum execution time 180second". With groups return only Product data without translations.

What annotation or else manipulation must do for fix this issue? Please help!

Edit: Tried Use next queries:

public function findNextPageByBrandCategoryIds(array $cat_ids, $brand_id, $offset=0, $limit=8 )
    {
        $qb = $this->createQueryBuilder('p');

        if( !empty($cat_ids) ){
            $cat_ids = implode(',', $cat_ids);
            $qb->join('p.categories', 'c')
           ->where($qb->expr()->in('c.id', $cat_ids ) );
        }
        if( !empty($brand_id) ){
            $qb->andWhere('p.brand = :brand')
            ->setParameter('brand', $brand_id);
        }
        if( $offset>0 ){
            $qb->setFirstResult( $offset );
        }
        $qb->setMaxResults( $limit );
        return $qb->getQuery()->getResult();
    }

private function findNextPageByBrandCategoryIds($cat_id, $brand_id, $offset=0, $limit=8 )
    {
        $em = $this->getDoctrine()->getManager();
        $sql = "SELECT p.id, t.id AS translate_id " .
               "FROM product p INNER JOIN product_translation t ON t.translatable_id = p.id";

        $where .= ' WHERE 1=1 ' ;
        $rsm = new ResultSetMappingBuilder($em);

        if( !empty($cat_id) ){
            $sql .= " LEFT JOIN products_categories c ON c.product_id = p.id ";
            $where .= " AND c.category_id = ".$cat_id;
        }
        if( !empty($brand_id) ){
            $where .= " AND p.brand = ".$brand_id;
        }
        $limit = ' LIMIT '.$limit;

        if( $offset>0 ){
            $limit .= ' OFFSET '.$offset;
        }
        $sql = $sql.$where.$limit;

        $rsm->addRootEntityFromClassMetadata('AppBundle\Entity\Product', 'p');
        $rsm->addJoinedEntityFromClassMetadata('AppBundle\Entity\ProductTranslation', 't', 'p', 'product', array('id' => 'translatable_id'));
        $query = $em->createNativeQuery($sql, $rsm);
        return $query->getResult();
    }

Debug almost every line - they are right.

If use setHint(\Doctrine\ORM\Query::HINT_FORCE_PARTIAL_LOAD, true) - work but return products only, without translations.


Solution

  • Nik fix this issue: On Brand, Category and Product Entities

        use JMS\Serializer\Annotation\MaxDepth;
        /**
         * @MaxDepth(1)
        */
        private $products;
       /**
         * @MaxDepth(1)
          */
         private $categories;
    
         /**
        * @MaxDepth(1)
          */
         private $brand;