【问题标题】:A circular reference has been detected when serializing the object of class "App\Entity\User" (configured limit: 1)序列化类“App\Entity\User”的对象时检测到循环引用(配置限制:1)
【发布时间】:2020-04-03 17:04:02
【问题描述】:

我遇到了一个导致我出现此错误的问题:

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

我有一个企业实体,它有任务订单、车辆和用户。

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

还有一个与订单和公司有关系的用户实体。

所以我有这个: Entreprise.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;

Vehicule.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)

我在互联网上看到我必须用“maxdepth”做一些事情,但我不明白我必须做什么以及具体在哪里

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

   /**
     * 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(),
        ]);
    }

【问题讨论】:

  • 你能告诉我们你在用户实体上使用序列化程序的代码吗?
  • 是的,看最后的User实体,属性后面我有两个序列化函数
  • 您应该阅读有关序列化深度的信息:symfony.com/doc/current/components/…
  • 是的,我已经阅读了这部分,我知道我必须使用@Maxdepth,但问题是我不知道我应该把它放在哪里,放在哪个类?
  • 您的深度问题涉及 ordreMissions 和 entreprise,尝试将 depthmax 增加到这两个属性,以便序列化 User 将能够转到 ordreMissions 和 entreprise childrens

标签: symfony serialization reference circular-dependency depth


【解决方案1】:

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

用户

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 */]
);

但是,您还有两个选择,要么使用Handling Circular References,要么使用Handling Serialization Depth

【讨论】:

  • 感谢您的回复!那么我为什么要使用@Groups 概念而不是@MaxDepth?不是更简单吗?顺便说一句,不幸的是它仍然不起作用,我有同样的错误。事实上,在我的 json 中,我序列化并返回的不是$user,而是Vehicle object。但是我不太明白你是如何选择组的,所以我发现很难适应当前的情况:(。(我会用我的代码更新我的第一篇文章)
  • 我更喜欢使用 Group,因为它们提供了更大的灵活性。每个时间组都在上下文中根据需要序列化对象,但是使用 MaxDepth,您可以在所有应用程序中对一个对象进行一种表示。但是,您可以在“车辆”中的“不成熟”和“企业”中使用 Maxdepth
  • 好的,我明白了!所以我选择了@MaxDepth (2) 解决方案。我试图把它放在 doc ' 上,但它没有改变任何东西。我不知道我做得好不好。我用我创建的函数编辑了我的第一篇文章。她错了?
  • 试试@MaxDepth (1)
  • 实际上并没有考虑到这个限制。当我在 Vehicule 实体中注册和公司的 MaxDepth (2) 时,我总是在 Entity \ User 上遇到 (configured limit: 1) 错误。这意味着我没有把 maxDepth 放在正确的地方做错了
【解决方案2】:

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

use Symfony\Component\Serializer\SerializerInterface;

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      如果子实体有父实体并且您不想在序列化中将其作为另一个“子实体”.. 那么您可以尝试使用 Ignore use Symfony\Component\Serializer\Annotation\Ignore;

      $user->messages(): // 用户拥有一对多关系的消息

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

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

      【讨论】:

        【解决方案5】:

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

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

        它对我有用。

        【讨论】:

          猜你喜欢
          • 2022-12-11
          • 2012-05-04
          • 2012-12-01
          • 2023-04-03
          • 1970-01-01
          • 1970-01-01
          • 2015-01-21
          • 2010-11-12
          相关资源
          最近更新 更多