web-dev-qa-db-ja.com

Symfony 3.2循環参照が検出されました(設定された制限:1)

プロジェクトにこの2つのエンティティがあります

class PoliceGroupe
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="code", type="string", length=50)
     */
    private $code;

    /**
     * @ORM\ManyToMany(targetEntity="PointVente", inversedBy="policegroupe")
     * @ORM\JoinTable(name="police_groupe_point_vente",
     *      joinColumns={@ORM\JoinColumn(name="police_groupe_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="point_vente_id", referencedColumnName="id")}
     *      )
     */
    private $pointVente;
    /**
     * Constructor
     */
    public function __construct($produit)
    {
       $this->pointVente = new \Doctrine\Common\Collections\ArrayCollection();
    }
}

そして、ここに私の他のエンティティがあります

class PointVente
{
    /**
     * @var string
     *
     * @ORM\Column(name="abb", type="string", length=50)
     */
    private $abb;

    /**
     * @var string
     *
     * @ORM\Column(name="libelle", type="string", length=255)
     */
    private $libelle;

    /**
     *
     * @ORM\ManyToMany(targetEntity="PoliceGroupe", mappedBy="pointVente")
     */
    private $policegroupe;
    }

コントローラーでこのコードを実行しようとしています

$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ObjectNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$em = $this->getDoctrine()->getManager();
$data = $request->get('data');
$policegroupe=$em->getRepository('StatBundle:PoliceGroupe')->findOneBy(array('id' => $data));
$pointventes = $policegroupe->getPointVente();
$jsonContent = $serializer->serialize($pointventes, 'json');
return new JsonResponse( array('pointventes'=>$jsonContent) );

しかし、私はこの例外を取得します

Symfony\Component\Serializer\Exception\CircularReferenceException: A circular reference has been detected (configured limit: 1).
    at n/a
        in C:\wamp\www\Sys\vendor\symfony\symfony\src\Symfony\Component\Serializer\Normalizer\AbstractNormalizer.php line 194

doctrineアノテーションに従ってエンティティをマッピングしました。何かが足りませんか?

12
Chaymae

Symfony 3.2

useCircularReferenceLimitメソッドを使用します。例えば:

_$normalizer = new ObjectNormalizer();
$normalizer->setCircularReferenceLimit(2);
// Add Circular reference handler
$normalizer->setCircularReferenceHandler(function ($object) {
    return $object->getId();
});
$normalizers = array($normalizer);
$serializer = new Serializer($normalizers, $encoders);
_

その理由は、エンティティを循環参照すると、エンティティをシリアル化しようとすると問題が発生するためです。このメソッドの効果は、シリアル化階層の最大の深さを定義することです。

編集:循環参照ハンドラーを追加( 循環参照が検出されました(構成された制限:1)シリアライザーSYMFONY

編集:更新(Symfony 4.2)

Symfony 3.2で試されるが、ここで_circular_reference_limit_は問題ではありません(そして、デフォルトの1は問題ありません。そうでない場合、エンティティは2回取得されます)、問題はエンティティが_circular_reference_handler_。 idがエンティティ識別子であることを伝えることで問題は解決します。 Symfony Docs この段落の下部 をご覧ください。

setCircularReferenceHandlerは非推奨です コンテキストの次のキーを支持して _circular_reference_handler_であるため、次のように記述できます。

_// Tip : Inject SerializerInterface $serializer in the controller method
// and avoid these 3 lines of instanciation/configuration
$encoders = [new JsonEncoder()]; // If no need for XmlEncoder
$normalizers = [new ObjectNormalizer()];
$serializer = new Serializer($normalizers, $encoders);

// Serialize your object in Json
$jsonObject = $serializer->serialize($objectToSerialize, 'json', [
    'circular_reference_handler' => function ($object) {
        return $object->getId();
    }
]);

// For instance, return a Response with encoded Json
return new Response($jsonObject, 200, ['Content-Type' => 'application/json']);
_
27

最良の方法は、useCircularReferenceLimitメソッドを使用することです。この投稿で既に明確に説明されているように。

ただし、別のオプションがあります。オプションとして、Originオブジェクトの属性を無視する方法があります。シリアル化されたオブジェクトで絶対に必要ない場合は無視できます。このソリューションの利点は、シリアル化されたオブジェクトが小さくて読みやすいことであり、欠点は無視された属性を参照しなくなることです。

Symfony 2.3-4.1

これらの属性を削除するには、ノーマライザー定義でsetIgnoredAttributes()メソッドを使用します。

_use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

$normalizer = new ObjectNormalizer();
$normalizer->setIgnoredAttributes(array('age'));
$encoder = new JsonEncoder();

$serializer = new Serializer(array($normalizer), array($encoder));
$serializer->serialize($person, 'json'); // Output: {"name":"foo","sportsperson":false}
_

setIgnoredAttributes()メソッドはSymfony 2.3で導入されました。

Symfony 2.7より前では、属性はシリアライズ中にのみ無視されました。 Symfony 2.7以降、デシリアライズの際にも無視されます。

Symfony 4.2-5.0

Ignore_attributesオプションの代替として使用されたsetIgnoredAttributes()メソッドは、Symfony 4.2で廃止されました。

これらの属性を削除するには、目的のシリアライザーメソッドのコンテキストパラメーターの_ignored_attributes_キーを使用して配列を提供します。

_use Acme\Person;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$person = new Person();
$person->setName('foo');
$person->setAge(99);

$normalizer = new ObjectNormalizer();
$encoder = new JsonEncoder();

$serializer = new Serializer([$normalizer], [$encoder]);
$serializer->serialize($person, 'json', ['ignored_attributes' => ['age']]); // Output: {"name":"foo"}
_

Symfony 3.4プロジェクトでは、これら2つのメソッドsetIgnoredAttributes()setCircularReferenceLimit()を組み合わせて使用​​していますが、うまく機能します。

出典: https://symfony.com/doc/3.4/components/serializer.html

0
PHP php

同じ問題を修正

use JMS\Serializer\SerializerBuilder;
...

$products = $em->getRepository('AppBundle:Product')->findAll();
$serializer = SerializerBuilder::create()->build();
$jsonObject = $serializer->serialize($products, 'json');

読む ここ

0
Galina Bublik