Symfony序列化Doctrine实体

7

我有一个简单的实体类:

<?php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;


/**
 * @ORM\Entity(repositoryClass="CompanyUserRepository")
 * @ORM\Table(name="company_users")
 */
class CompanyUser
{
/**
 * @ORM\Column(type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @ORM\Column(type="string", length=100)
 */
private $firstName;

/**
 * @ORM\Column(type="string", length=100)
 */
private $lastName ;

/**
 * @ORM\OneToMany(targetEntity="Score", mappedBy="user")
 */
private $scores;
/**
 * Constructor
 */
public function __construct()
{
    $this->scores = new ArrayCollection();
}

/**
 * Get id
 *
 * @return integer
 */
public function getId()
{
    return $this->id;
}

/**
 * Set firstName
 *
 * @param string $firstName
 *
 * @return CompanyUser
 */
public function setFirstName($firstName)
{
    $this->firstName = $firstName;

    return $this;
}

/**
 * Get firstName
 *
 * @return string
 */
public function getFirstName()
{
    return $this->firstName;
}

/**
 * Set lastName
 *
 * @param string $lastName
 *
 * @return CompanyUser
 */
public function setLastName($lastName)
{
    $this->lastName = $lastName;

    return $this;
}

/**
 * Get lastName
 *
 * @return string
 */
public function getLastName()
{
    return $this->lastName;
}

/**
 * Add score
 *
 * @param \AppBundle\Entity\Score $score
 *
 * @return CompanyUser
 */
public function addScore(\AppBundle\Entity\Score $score)
{
    $this->scores[] = $score;

    return $this;
}

/**
 * Remove score
 *
 * @param \AppBundle\Entity\Score $score
 */
public function removeScore(\AppBundle\Entity\Score $score)
{
    $this->scores->removeElement($score);
}

/**
 * Get scores
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getScores()
{
    return $this->scores;
}

当我尝试获取所有用户并将它们序列化为JSON时,问题就出现了:

/**
 * @Route("/api/getUsers", name="getUsers")
 */
public function getUsers(Request $request){
    $users = $this->getDoctrine()
    ->getRepository('AppBundle:CompanyUser')
    ->findAll();

    $serializer = $this->get('serializer');
    $data = $serializer->serialize($users, 'json');

    return new Response($users);
}

我遇到了“检测到循环引用(配置限制:1)”的问题。当我删除getScores getter时,一切正常。我只需要获取id、firstName和lastName。有没有不序列化其他对象的方法?


1
实现\Serializable接口对于可能被序列化的对象来说是一个好习惯。请注意这一点。 - Muriano
1个回答

9

嗯,在序列化带关系的实体时,处理循环引用是一件常见的事情。

解决方案1:实现可序列化接口,并使关系属性不可序列化/反序列化(在大多数情况下,这是有效的解决方案)。

解决方案2:此规范器的setCircularReferenceLimit()方法设置了在将同一对象序列化多少次之前将其视为循环引用的次数。它的默认值为1。因此,在调用serialize()方法之前,请执行以下操作:

public function getUsers(Request $request){
    $users = $this->getDoctrine()
    ->getRepository('AppBundle:CompanyUser')
    ->findAll();

    $serializer = $this->get('serializer');
    $serializer->setCircularReferenceLimit(2); // Change this with a proper value for your case
    $data = $serializer->serialize($users, 'json');

    return new Response($data);
}

**** 更新 ****

正如 @Derek 在评论中所说,解决方案2在某些Symfony版本中可能无效。那么您可以尝试以这种方式设置循环引用的处理程序:

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

$normalizer->setCircularReferenceHandler(function ($object) {
   return $object->getName(); // Change this to a valid method of your object
});

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

这应该返回实体值,而不是迭代关系。

你的第二个解决方案不起作用。setCircularReferenceLimit()方法不属于Serializer类,而是属于AbstractNormalizer类。在Symfony 2.8中,你的代码会抛出致命错误。我找不到从序列化器服务中获取此规范化器的方法,因为getNormalizer()方法是私有的... - Derek
getNormalizer()方法是私有的,因此无法使用(并且它需要2个参数)。似乎只能在将规范化器注入序列化器之前自定义规范化器... - Derek
抱歉上次评论匆忙,@Derek。我已经更新了我的回复,并添加了一种新的处理此错误的方法。 - Muriano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接