【问题标题】:Symfony 3.0.4 Circular reference detected during serialization with FOSRestBundleSymfony 3.0.4 在使用 FOSRestBundle 序列化期间检测到循环引用
【发布时间】:2016-04-21 16:48:03
【问题描述】:

我在 Symfony 项目中使用 FOSRestBundle。当我尝试处理视图时,它在使用 Symfony 序列化器和 JMSSerializer 序列化我的数据期间失败。

这是呈现响应的方法:

DefaultController.php

$em = $this->getDoctrine()->getManager('magellan');
$qb = $em->createQueryBuilder();

$query = $qb->select('h')
        ->from('DataBundle:Holding', 'h')
        ->where($qb->expr()->eq('h.id', ':holding_id'))
        ->setParameter('holding_id', $holding_id)
        ->getQuery();

$results = $query->getResult();

$view = $this->view($results, 200);

// Everything's ok up to this point

return $this->handleview($view);

这些是我的实体:

Holding.php

class Holding
{

    ...

    /**
     * @ORM\OneToMany(targetEntity="Subsidiary", mappedBy="holding")
     */
    private $subsidiaries;
}

Subsidiary.php

class Subsidiary
{

    ...

    /**
     * @ORM\ManyToOne(targetEntity="Holding", inversedBy="subsidiaries")
     * @ORM\JoinColumn(name="id_holding", referencedColumnName="id_holding")
     */
    private $holding;

    /**
     * @ORM\OneToMany(targetEntity="Brand", mappedBy="subsidiary")
     */
    private $brands;
}

品牌.php

class Brand
{

    ...

    /**
     * @ORM\ManyToOne(targetEntity="Subsidiary", inversedBy="brands")
     * @ORM\JoinColumn(name="id_subsidiary", referencedColumnName="id_subsidiary")
     */
    private $subsidiary;

    /**
     * @ORM\OneToMany(targetEntity="Product", mappedBy="brand")
     */
    private $products;
}

Product.php

class Product
{

    ...

    /**
     * @ORM\ManyToOne(targetEntity="Brand", inversedBy="products")
     * @ORM\JoinColumn(name="id_brand", referencedColumnName="id_brand")
     */
    private $brand;

    /**
     * @ORM\ManyToOne(targetEntity="Sector", inversedBy="products")
     * @ORM\JoinColumn(name="id_sector", referencedColumnName="id_sector")
     */
    private $sector;

    /**
     * @ORM\OneToMany(targetEntity="Commercial", mappedBy="product")
     */
    private $commercials;
}

Commercial.php

class Commercial
{

    ...

    /**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="commercials")
     * @ORM\JoinColumn(name="id_product", referencedColumnName="id_product")
     */
    private $product;

    /**
     * @ORM\OneToMany(targetEntity="CommercialReport", mappedBy="commercial")
     */
    private $reports;

CommercialReport.php

class CommercialReport
{

    ...

    /**
     * @ORM\ManyToOne(targetEntity="Commercial", inversedBy="reports")
     * @ORM\JoinColumn(name="id_commercial", referencedColumnName="id_commercial")
     */
    private $commercial;
}

Sector.php

class Sector
{

    ...

    /**
     * @ORM\OneToMany(targetEntity="Product", mappedBy="sector")
     */
    private $products;
}

使用默认的 symfony 序列化程序时,我收到以下错误:

"message":"检测到循环引用(配置限制: 1).","class":"Symfony\Component\Serializer\Exception\CircularReferenceException"

当使用 JMSSerializer 时,当我转到控制器的相应页面时,页面永远不会完成加载。同时在 dev.log 文件中,每秒都会添加带有对我的数据库的请求的新 Doctrine.debug 条目。

【问题讨论】:

标签: rest symfony serialization doctrine-orm circular-reference


【解决方案1】:
    $normalizers->setCircularReferenceHandler(function ($object) {
        return $object->getId();
    });

如果你的 objectNormalizer() 在你创建实例后添加它 它对我来说很完美

【讨论】:

    【解决方案2】:

    如果您使用 FosRestBundle,则可以将 GROUPS 用于序列化程序。 FosRestBundle 给出了一个注解:@FOS\RestBundle\Controller\Annotations\View(serializerGroups={"user"})

    您的组可以排除循环属性。

    您可以这样做的另一个想法。在你的 app/config/services.yml

    circular_reference_handler:
        public: false
        class: callback
        factory: [AppBundle\Serializer\CircularHandlerFactory, getId]
    serializer.normalizer.object:
        class: Symfony\Component\Serializer\Normalizer\ObjectNormalizer
        arguments: ["@serializer.mapping.class_metadata_factory", null, "@serializer.property_accessor"]
        public: false
        tags: [serializer.normalizer]
        calls:
            - method: setCircularReferenceLimit
              arguments: [1]
            - method: setCircularReferenceHandler
              arguments: ["@circular_reference_handler"]
    

    工厂可以是这样的:

    namespace AppBundle\Serializer;
    
    class CircularHandlerFactory
    {
        /**
         * @return \Closure
         */
        public static function getId()
        {
            return function ($object) {
                return $object->getId();
            };
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-26
      • 2016-12-15
      • 2017-04-06
      • 2012-05-04
      • 2012-12-01
      相关资源
      最近更新 更多