我有一个实体调用Category,另一个调用Product,中间一个名为CategoryProduct。
@ORM\OneToMany(targetEntity="CategoryProduct", mappedBy="Catego", fetch="EAGER")
在CategoryProduct类中(在$ catego上)具有反dBy。@ORM\OneToOne(targetEntity="Product", inversedBy="Category")
之间具有一个OneToOne关系,在Product类中(在$ category上)具有inversedBy。在我的CategoryController里面,我有一个像这样的函数:
public function getCategoryAction(Request $request)
{
$category = $this->get('doctrine.orm.entity_manager')
->getRepository('AppBundle:Category')
->findAll();
return new JsonResponse($category);
}
返回给出实体类别的集合,但是“子实体”产品为空。当我在Symfony中检查用于调试的Token时,我在“ Doctrine”部分中进行了检查,并且查询工作正常,数据已加载,但返回时不在这里。我可以使用$category->getProduct()
访问数据(它为我提供了所需的指向类别的Product链接的集合),但我的Product子类仍然为空。有人知道为什么吗?
感谢您的帮助。
答案 0 :(得分:0)
从头开始处理当前的问题是典型的教义水合问题。
默认情况下,Doctrine会延迟加载关系,这意味着,Doctrine最初会提供不包含任何元素的代理集合,并且仅在以某种方式访问实际元素时(例如,使用诸如getProduct( ))。这就是为什么您的“产品”收藏集看起来空白的原因。
您可以通过将关联中的fetch属性设置为EAGER来轻松更改此设置:
// inside Category class
/**
* @ManyToOne(targetEntity="Product", fetch="EAGER")
*/
private $products;
但是最终最终将无法使您的代码正常工作,因为当您尝试对具有私有属性的对象进行json_encode时,您只会得到一个空的json。解决您的问题的方法是使用自定义方式来序列化对象。最简单(也可能是最好)的解决方案是使用Symfony序列化器组件。但是您应该知道,仅使用$serializer->serialize($category, 'json');
会引发循环引用异常。造成这种情况的原因是(据我猜测)您还在Product类中保留了对Category的引用,如下所示:
// inside Product class
/**
* @OneToMany(targetEntity="Category")
*/
private $category;
您可以想象,Symfony将尝试序列化一个类别,该类别包含很多产品,这些产品具有一个类别,很多产品...这是一个循环引用。
要绕过此问题,您应该使用如下序列化组:
// inside your controller, supposing you are using autowiring to inject services:
use Symfony\Component\Serializer\SerializerInterface;
public function getTariffsAction(Request $request, SerializerInterface $serializer)
{
$category = $this->get('doctrine.orm.entity_manager')
->getRepository('AppBundle:Category')
->findAll();
$categoryJson = $serializer->serialize($category, 'json', ['groups' => ['tariffs'] ]);
return $this->json($categoryJson);
}
然后显式配置对象的属性,您希望这样进入实体:
// Category.php
use Symfony\Component\Serializer\Annotation\Groups;
...
/**
* @ORM\Id
* @Groups({"tariffs"})
*/
protected $id;
/**
* @ORM\Column(type="string")
* @Groups({"tariffs"})
*/
protected $name;
/**
* @ORM\ManyToOne(targetEntity="Product")
* @Groups({"tariffs"})
*/
private $product;
// any other attribute you want to include
最后在您的Product.php中:
Product.php
/**
* @ORM\Id
* @Groups({"tariffs"})
*/
protected $id;
/**
* @ORM\Column(type="string")
* @Groups({"tariffs"})
*/
protected $productName;
// do not include the reference to the category to avoid circular reference
/**
* @OneToMany(targetEntity="Category")
*/
private $category;
您可以在documentation中找到有关序列化程序组件和序列化组的更多信息。
答案 1 :(得分:0)
在我的Controller更新下方,使用您给我的方法。
public function getTariffsAction(Request $request, SerializerInterface $serializer)
{
$category = new Category();
$category = $this->get('doctrine.orm.entity_manager')
->getRepository('AppBundle:Category')
->findAll();
$categoryJson = $serializer->serialize($category , 'json', ['groups' => ['tariffs'] ]);
return $this->json($categoryJson);
}
当我转储$ category时,我得到了一些我无法粘贴的东西,因为它太多了。使用Postman会使我的计算机出现很多错误(屏幕之一关闭),之后我必须重新启动
答案 2 :(得分:0)
问题已经解决,您绝对正确,这是循环引用,我按照您所说的与小组一起解决了。 (我使用FOSRestBundle进行分组比使用本机symfony方法更容易)