序列化“App\Entity\User”类的对象时检测到循环引用(配置限制:1)

问题描述 投票:0回答:10

我遇到的问题给了我这个错误:

序列化对象时检测到循环引用 类“App\Entity\User”(配置限制:1)

我有一个包含任务订单、车辆和用户的企业实体。

与用户、公司和车辆有关系的订单实体。

以及与订单和公司有关系的用户实体。

所以我有这个: 企业.php

class Entreprise
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;


    /**
     * @ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="entreprise", orphanRemoval=true)
     */
    private $users;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Vehicule", mappedBy="entreprise", orphanRemoval=true)
     */
    private $vehicules;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\OrdreMission", mappedBy="entreprise", orphanRemoval=true)
     */
    private $ordreMissions;

OrdreMission.php:

class OrdreMission
{

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * Agent qui réalisera la mission
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="ordreMissions")
     * @ORM\JoinColumn(nullable=false)
     */
    private $user;


    /**
     * Immatriculation de la voiture de service
     * @ORM\ManyToOne(targetEntity="App\Entity\Vehicule")
     */
    private $vehicule;



    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Entreprise", inversedBy="ordreMissions")
     * @ORM\JoinColumn(nullable=false)
     */
    private $entreprise;

车辆.php:

class Vehicule
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * Marque du véhicule
     * @ORM\Column(type="string", length=255)
     */
    private $marque;

    /**
     * Modèle du véhicule
     * @ORM\Column(type="string", length=255)
     */
    private $modele;

    /**
     * Immatriculation du véhicule
     * @ORM\Column(type="string", length=255)
     * @MaxDepth(2)
     */
    private $immatriculation;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Entreprise", inversedBy="vehicules")
     * @ORM\JoinColumn(nullable=false)
     * @MaxDepth(2)
     */
    private $entreprise;

用户.php:

class User implements UserInterface, Serializable
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * Adresse email de l'utilisateur
     * @ORM\Column(type="string", length=180, unique=true)
     * @Assert\NotBlank()
     * @Assert\Email(message="Veuillez renseigner un email valide")
     */
    private $email;

    /**
     * Rôles de l'utilisateur
     * @ORM\Column(type="json")
     */
    private $roles = [];


    /**
     * Ordres de mission de l'utilisateur
     * @ORM\OneToMany(targetEntity="App\Entity\OrdreMission", mappedBy="user")
     */
    private $ordreMissions;


    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Entreprise", inversedBy="users")
     * @ORM\JoinColumn(nullable=false)
     */
    private $entreprise;

/**
 * String representation of object
 * @link http://php.net/manual/en/serializable.serialize.php
 * @return string the string representation of the object or null
 */
public function serialize()
{
    return serialize([
        $this->id,
        $this->email,
        $this->password,
    ]);
}

/**
 * Constructs the object
 * @link http://php.net/manual/en/serializable.unserialize.php
 * @param string $serialized <p>
 * The string representation of the object.
 * </p>
 * @return void
 */
public function unserialize($serialized)
{
    list (
        $this->id,
        $this->email,
        $this->password,
        ) = unserialize($serialized);
}

当我想添加新车辆时,出现错误:

序列化对象时检测到循环引用 类“App\Entity\User”(配置限制:1)

我在互联网上看到我必须做一些带有“最大深度”的事情,但我不明白我必须做什么以及具体在哪里

这是我用来添加车辆对象并发送它的功能控制器:

   /**
     * Pour créer un nouveau véhicule
     * 
     * @Route("/chef-service/ordres-mission/new/new-vehicule", name="vehicule_create")
     * @IsGranted({"ROLE_CHEF_SERVICE"})
     * @Method({"POST"})
     * @return Response
     */
    public function createVehicule(Request $request, EntityManagerInterface $manager)
    {
        $vehicule = new Vehicule();
        $vehicule->setEntreprise($this->adminService->getEntreprise());

        $form = $this->createForm(VehiculeType::class, $vehicule, [
            'action' => $this->generateUrl($request->get('_route'))
        ]);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {

            $encoders = array(new XmlEncoder(), new JsonEncoder());
            $normalizers = array(new ObjectNormalizer());
            $serializer = new Serializer($normalizers, $encoders);
            $manager->persist($vehicule);
            $manager->flush();

            $result = $serializer->normalize(
                [
                    'code' => 200,
                    'message' => 'OK',
                    'vehicule' => $vehicule,
                ],
                null,
                [AbstractObjectNormalizer::ENABLE_MAX_DEPTH => true]
            );
            
            $jsonContent = $serializer->serialize(
                $result,
                'json'
            );
            return new Response($jsonContent);

        }

        return $this->render('ordre_mission/partials/newVehicule.html.twig', [
            'formVehicule' => $form->createView(),
        ]);
    }
symfony serialization reference circular-dependency depth
10个回答
18
投票

对我来说,当我使用API平台时会发生此错误(可能与此案例无关,但可能对其他人有帮助)我必须遵循此评论

是因为该Entity没有被@ApiResource标记,所以不是 由 API 平台处理(由 Symfony 平台处理),并且如下 是循环引用,会抛出错误。如果该实体 API资源,循环引用会自动处理。 如果你不想让它成为资源,你需要注册一个 自己的循环引用处理程序: https://symfony.com/doc/current/components/serializer.html#handling-circular-references


14
投票

尝试使用序列化组来避免循环引用(适用于 Symfony Serializer 和 jms Serializer)。 当您序列化“用户”时不序列化其他实体的“用户”时的示例。

用户

class User 
{

/**
 * @Groups("user")
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @Groups("user")
 * @ORM\ManyToOne(targetEntity="App\Entity\Entreprise", inversedBy="users")
 * @ORM\JoinColumn(nullable=false)
 */
private $entreprise;
}

企业

class Entreprise
{
/**
 * @Groups("entreprise")
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;


/**
 * @Groups("user_detail")
 * @ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="entreprise", orphanRemoval=true)
 */
private $users;

然后

$json = $serializer->serialize(
    $user,
    'json', ['groups' => ['user','entreprise' /* if you add "user_detail" here you get circular reference */]
);

但是,您还有两个选择,要么使用处理循环引用,要么使用处理序列化深度


10
投票

在我的例子中,我修复了注入序列化器服务,而不是在控制器方法中创建新的序列化器实例。

use Symfony\Component\Serializer\SerializerInterface;

//...
public function createOrder(Request $request, SerializerInterface $serializer)
{
    //...
    $json = $serializer->serialize($order, 'json', ['groups' => ['normal']]);
    //...
}

9
投票

如果子实体有父实体,并且您不想在序列化中将其作为另一个“子实体”。那么您可以尝试使用“忽略”

use Symfony\Component\Serializer\Annotation\Ignore;

$user->messages(): // 用户有关系为 oneToMany 的消息

然后在 Message 中添加 Ignore to $user:

class Message
// ...
/** @Ignore() */
$user;

4
投票

CIRCULAR_REFERENCE 错误,这是序列化器调用对象序列化器时防止无限循环的错误。这种情况通常发生在具有多对一和多对多关系的实体上。为了解决这个问题,我们需要通过关注对象 id 来处理序列化器的自定义上下文。

因此在您的控制器中,可以按照下一个示例来完成:

return $this->json($data,Response::HTTP_OK,[],
[ObjectNormalizer::CIRCULAR_REFERENCE_HANDLER=>function ($obj){return $obj->getId();}]);

以及使用序列化器

$encoder = new JsonEncoder();
$defaultContext = [
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object, $format, $context) {
    return $object->getName();
},];
$normalizer = new ObjectNormalizer(null, null, null, null, null, null, $defaultContext);
$serializer = new Serializer([$normalizer], [$encoder]);

有关更多信息,请查看 symfony 文档 https://symfony.com/doc/current/components/serializer.html#handling-circular-references


2
投票

对于错误“参考通函”

您必须在要显示的每个属性前面(在您的实体中)标记注释 @Groups("post:read") 然后不要忘记 use 语句“use Symfony\Component\Serializer\Annotation\Groups;” (在您的控制器中)


0
投票

我利用了 ControllerTrait 的方法“json”:

return $this->json($result, Response::HTTP_OK, [], ['groups' => 'user','entreprise']);

它对我有用。


0
投票

我发现您可以将循环引用限制传递给serialize()上下文,似乎可以这样做,因为在错误页面中我可以看到[...](配置的限制:10)。例如:

$yourNumber = 2;
$result = $serializer->normalize(
     [
        'code' => 200,
        'message' => 'OK',
        'vehicule' => $vehicule,
      ],
 null,
      [
         AbstractObjectNormalizer::ENABLE_MAX_DEPTH => true,
         AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT => $yourNumber
        ]
);

希望对您有帮助。


0
投票

你好,我有同样的错误在此处输入图像描述

有解决办法 在此输入图片描述

在控制器的功能中,您还必须进行一些更改 我更改这一行: $dataArray[] = $this->serializer->normalize($typeDeclaration); 与此: $dataArray[] = $this->serializer->normalize($typeDeclaration, null, ['groups' => 'type_declaration']); 抱歉我的英语不好 XD,GL


-1
投票

也许这是实体类中的集合类型问题。

当您创建 ManyToOne、OneToMany 或 ManyToMany 类型的关系时,它会出现。要解决这个问题,你可以尝试这个代码;):

示例:

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\ClientRepository;
use App\Entity\Client;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;


class ClientController extends AbstractController
{
    /**
     * @Route("/api/client", methods="GET")
     */
    public function index(ClientRepository $repository, SerializerInterface $serializer): Response
    { 
        //For avoiding Collection issues of ManyToOne || OneToMany || ManyToMany
        //relationship between 2 entities
        return $this->json(
            json_decode(
                $serializer->serialize(
                    $repository->findAll(),
                    'json',
                    [AbstractNormalizer::IGNORED_ATTRIBUTES => ['commandes']]
                ),
                JSON_OBJECT_AS_ARRAY
            )
        );
    }
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.