gpt4 book ai didi

php - Symfony 3 Doctrine 2 : Circular reference on relations

转载 作者:行者123 更新时间:2023-12-04 23:26:08 28 4
gpt4 key购买 nike

我正在尝试使用 Doctrine 2 在 Symfony 3 中使用 4 个实体,但是当我想序列化一个 Account 实体时,我遇到了循环引用异常:

A circular reference has been detected (configured limit: 1).

我在我的实体和模式中选择了双向关系是这样的:

 - Account [1] ---- [0..*] AccountSheet
- AccountSheet [1] ---- [0..*] Operation
- Operation [0..*] ---- [1] Category

以下是实体(为清晰起见,进行了一些清理):

src\AppBundle\Entity\Account.php

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;

/**
* @ORM\Entity()
* @ORM\Table(name="accounts",
* uniqueConstraints={@ORM\UniqueConstraint(name="accounts_name_unique",columns={"name"})})
*/
class Account extends AbstractGenericEntity{
/**
* @ORM\OneToMany(targetEntity="AccountSheet", mappedBy="account")
* @var AccountSheet[]
*/
protected $accountSheets;

public function __construct($name = null, $description = null){
$this->accountSheets = new ArrayCollection();
$this->name = $name;
$this->description = $description;
}
}

src\AppBundle\Entity\AccountSheet.php

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;

/**
* @ORM\Entity()
* @ORM\Table(name="accounts_sheets",
* uniqueConstraints={@ORM\UniqueConstraint(name="accountsheet_account_unique", columns={"name", "account_id"})})
* @ORM\HasLifecycleCallbacks
*/
class AccountSheet extends AbstractGenericEntity{

/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Account", inversedBy="accountSheets")
* @var Account
*/
protected $account;

/**
* @ORM\OneToMany(targetEntity="Operation", mappedBy="accountSheet")
* @var Operation[]
*/
protected $operations;

public function __construct($name = null){
$this->operations = new ArrayCollection();
$this->name = $name;
}
}

src\AppBundle\Entity\Operation.php

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\AbstractGenericEntity;

/**
* @ORM\Entity()
* @ORM\Table(name="operations")
*/
class Operation extends AbstractGenericEntity{
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\AccountSheet", inversedBy="operations")
* @ORM\JoinColumn(nullable=false)
* @var AccountSheet
*/
protected $accountSheet;

/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="operations")
* @var Category
*/
protected $category;

public function __construct($type = null, $label = null, $montant = null, $comment = null){
$this->label = $label;
$this->type = $type;
$this->comment = $comment;
$this->montant = $montant;
}
}

src\AppBundle\Entity\Category.php

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;

/**
* @ORM\Entity()
* @ORM\Table(name="categories")
*/
class Category extends AbstractGenericEntity{

/**
* @ORM\Column(type="string")
*/
protected $label;

/**
* @ORM\Column(type="string")
*/
protected $description;

/**
* @ORM\OneToMany(targetEntity="Operation", mappedBy="category")
* @var Operation[]
*/
protected $operations;

public function __construct($name = null){
$this->operations = new ArrayCollection();
$this->name = $name;
}
}

我猜它在 Operation 实体上,其中再次引用了 AccountSheet。双向操作并不是真正需要的。

我该如何重新排列它?

谢谢!

最佳答案

来自官方文档:

Circular references are common when dealing with entity relations

To avoid infinite loops, GetSetMethodNormalizer throws a CircularReferenceException when such a case is encountered:

$member = new Member();
$member->setName('Kévin');

$org = new Organization();
$org->setName('Les-Tilleuls.coop');
$org->setMembers(array($member));

$member->setOrganization($org);

echo $serializer->serialize($org, 'json'); // Throws a CircularReferenceException

因此,从这一点来看,您有 3 个解决方案来解决此问题:

  1. 设置循环引用处理程序:

Instead of throwing an exception, circular references can also be handled by custom callables. This is especially useful when serializing entities having unique identifiers:

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

$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getName();
});

$serializer = new Serializer(array($normalizer), array($encoder));
var_dump($serializer->serialize($org, 'json'));
// {"name":"Les-Tilleuls.coop","members":[{"name":"K\u00e9vin", organization: "Les-Tilleuls.coop"}]}
  1. 设置忽略的属性(不是我的首选解决方案):

在你的情况下:

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

normalizer->setIgnoredAttributes(array("account", "accountSheet", "category", "operation"));

$serializer = new Serializer(array($normalizer), array($encoder));
var_dump($serializer->serialize($org, 'json'));
  1. 使用组属性(我的首选解决方案):此方法类似于设置忽略的属性,因为您将通过在其上添加组注释来选择要序列化的属性,其余的将在规范化过程中被递归忽略。

Using Serialization Groups Annotations

Attributes Groups

例如,在您使用帐户实体的情况下,在帐户端执行此操作:

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\AbstractGenericEntity;
use Symfony\Component\Serializer\Annotation\Groups;

/**
* @ORM\Entity()
* @ORM\Table(name="accounts",
* uniqueConstraints={@ORM\UniqueConstraint(name="accounts_name_unique",columns={"name"})})
*/
class Account extends AbstractGenericEntity{
/**
* @ORM\OneToMany(targetEntity="AccountSheet", mappedBy="account")
* @var AccountSheet[]
* @Groups({"account"})
*/
protected $accountSheets;

public function __construct($name = null, $description = null){
$this->accountSheets = new ArrayCollection();
$this->name = $name;
$this->description = $description;
}
}

然后不要将此组注释放在 AccountSheet 实体中的 $account 字段上,以消除循环引用问题。

最后序列化您的帐户:

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

$serializer = new Serializer(array($normalizer), array($encoder));
var_dump($serializer->serialize($account, 'json', array('groups' => array('account')) ));

关于php - Symfony 3 Doctrine 2 : Circular reference on relations,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42470493/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com