Symfony 3.2 检测到循环引用(配置限制:1)
Symfony 3.2 A circular reference has been detected (configured limit: 1)
我的项目中有这两个实体
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
我根据学说注释映射了我的实体。我错过了什么吗?
Symfony 3.2
使用setCircularReferenceLimit
方法。例如:
$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);
原因是当您尝试序列化实体时,实体中的循环引用会导致一些问题。该方法的作用是定义序列化层级的最大深度。
编辑:添加了循环引用处理程序(A circular reference has been detected (configured limit: 1) Serializer SYMFONY)
编辑:更新 (Symfony 4.2)
要尝试使用 Symfony 3.2,但 circular_reference_limit
不是这里的问题(默认为 1 就可以,否则你的实体将被检索 2 次),问题是实体的方式由 circular_reference_handler
处理。告诉 id
是实体标识符可以解决问题。请参阅 Symfony 文档 at the bottom of this paragraph。
由于 setCircularReferenceHandler
已弃用 in favour of the following keys of the context 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']);
解决了同样的问题
use JMS\Serializer\SerializerBuilder;
...
$products = $em->getRepository('AppBundle:Product')->findAll();
$serializer = SerializerBuilder::create()->build();
$jsonObject = $serializer->serialize($products, 'json');
阅读here
最好的方法是使用useCircularReferenceLimit
方法。因为在这个post.
里面已经解释的很清楚了
但我们还有另一种选择。作为一种选择,有一种方法可以忽略来自原始对象的属性。如果我们在序列化对象中绝对不需要它,我们可以忽略它。
这种方案的优点是序列化后的对象更小更易读,缺点是我们不会再引用被忽略的属性
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}
Symfony 2.3 中引入了 setIgnoredAttributes()
方法。
在 Symfony 2.7 之前,属性只会在序列化时被忽略。从 Symfony 2.7 开始,它们在反序列化时也会被忽略。
Symfony 4.2 - 5.0
在 Symfony 4.2 中弃用了用作 ignored_attributes 选项替代方法的 setIgnoredAttributes()
方法。
要删除这些属性,请通过所需序列化程序方法的上下文参数中的 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 项目中,我混合使用了这两种方法 setIgnoredAttributes()
和 setCircularReferenceLimit()
,并且效果很好。
您需要使用上下文:
$normalizer->normalize($article, 'It doesn`t matter', [
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function($object) {
return $object->getId();
}
]);
大例子:
namespace App\Command;
use App\Entity\Oltp\Article;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use function json_encode;
class SqliteFirstCommand extends Command
{
protected static $defaultName = 'app:first';
private EntityManagerInterface $entityManager;
private NormalizerInterface $normalizer;
public function __construct(
EntityManagerInterface $entityManager,
NormalizerInterface $normalizer
)
{
parent::__construct(self::$defaultName);
$this->entityManager = $entityManager;
$this->normalizer = $normalizer;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$articles = $this->entityManager->getRepository(Article::class)->findAll();
foreach ($articles as $article) {
$array = $this->normalizer->normalize($article, 'It doesn`t matter', [
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function($object) {
return $object->getId();
}
]);
$output->writeln(json_encode($array));
}
return 0;
}
}
我的项目中有这两个实体
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
我根据学说注释映射了我的实体。我错过了什么吗?
Symfony 3.2
使用setCircularReferenceLimit
方法。例如:
$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);
原因是当您尝试序列化实体时,实体中的循环引用会导致一些问题。该方法的作用是定义序列化层级的最大深度。
编辑:添加了循环引用处理程序(A circular reference has been detected (configured limit: 1) Serializer SYMFONY)
编辑:更新 (Symfony 4.2)
要尝试使用 Symfony 3.2,但 circular_reference_limit
不是这里的问题(默认为 1 就可以,否则你的实体将被检索 2 次),问题是实体的方式由 circular_reference_handler
处理。告诉 id
是实体标识符可以解决问题。请参阅 Symfony 文档 at the bottom of this paragraph。
由于 setCircularReferenceHandler
已弃用 in favour of the following keys of the context 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']);
use JMS\Serializer\SerializerBuilder;
...
$products = $em->getRepository('AppBundle:Product')->findAll();
$serializer = SerializerBuilder::create()->build();
$jsonObject = $serializer->serialize($products, 'json');
阅读here
最好的方法是使用useCircularReferenceLimit
方法。因为在这个post.
但我们还有另一种选择。作为一种选择,有一种方法可以忽略来自原始对象的属性。如果我们在序列化对象中绝对不需要它,我们可以忽略它。 这种方案的优点是序列化后的对象更小更易读,缺点是我们不会再引用被忽略的属性
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}
Symfony 2.3 中引入了 setIgnoredAttributes()
方法。
在 Symfony 2.7 之前,属性只会在序列化时被忽略。从 Symfony 2.7 开始,它们在反序列化时也会被忽略。
Symfony 4.2 - 5.0
在 Symfony 4.2 中弃用了用作 ignored_attributes 选项替代方法的 setIgnoredAttributes()
方法。
要删除这些属性,请通过所需序列化程序方法的上下文参数中的 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 项目中,我混合使用了这两种方法 setIgnoredAttributes()
和 setCircularReferenceLimit()
,并且效果很好。
您需要使用上下文:
$normalizer->normalize($article, 'It doesn`t matter', [
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function($object) {
return $object->getId();
}
]);
大例子:
namespace App\Command;
use App\Entity\Oltp\Article;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use function json_encode;
class SqliteFirstCommand extends Command
{
protected static $defaultName = 'app:first';
private EntityManagerInterface $entityManager;
private NormalizerInterface $normalizer;
public function __construct(
EntityManagerInterface $entityManager,
NormalizerInterface $normalizer
)
{
parent::__construct(self::$defaultName);
$this->entityManager = $entityManager;
$this->normalizer = $normalizer;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$articles = $this->entityManager->getRepository(Article::class)->findAll();
foreach ($articles as $article) {
$array = $this->normalizer->normalize($article, 'It doesn`t matter', [
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function($object) {
return $object->getId();
}
]);
$output->writeln(json_encode($array));
}
return 0;
}
}