【发布时间】:2015-04-06 22:54:51
【问题描述】:
在尝试使用自引用 ManyToOne 实体时,我发现子项的数量取决于用于查找父项的方法。如果使用存储库,则测试失败并显示Failed asserting that 1 matches expected 2。如果改为使用 DQL,则测试成功。请参阅下面的测试部分中的testTwoKids()。我已经在调试中确认数据库中的实际计数在这两种情况下都是 2。
我的猜测是实体定义有问题。
实体:
class Category
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* @ORM\Column(name="name", type="string", nullable=false)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
**/
private $children;
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="children", cascade={"persist","remove"})
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
**/
private $parent;
public function __construct() {
$this->children = new ArrayCollection();
}
public function addChildren($child)
{
$this->children[] = $child;
return $this;
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function setParent($parent)
{
$this->parent = $parent;
}
public function getParent()
{
return $this->parent;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add children
*
* @param \AppBundle\Entity\Category $children
* @return Category
*/
public function addChild($child)
{
$this->children->add($child);
$child->setParent($this);
return $this;
}
/**
* Remove children
*
* @param \AppBundle\Entity\Category $children
*/
public function removeChild(\AppBundle\Entity\Category $children)
{
$this->children->removeElement($children);
}
/**
* Get children
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
}
测试
class CategoryTest extends KernelTestCase
{
/**
* @var \Doctrine\ORM\EntityManager
*/
private $em;
/**
* {@inheritDoc}
*/
public function setUp()
{
self::bootKernel();
$this->em = static::$kernel->getContainer()
->get('doctrine')
->getManager()
;
$product = new \AppBundle\Entity\Product();
$product->setName('foo');
$this->em->persist($product);
$cat = new \AppBundle\Entity\Category();
$cat->setName('Hook');
$child = new \AppBundle\Entity\Category();
$child->setName('Dry');
$child->setParent($cat);
$this->em->persist($child);
$this->em->flush();
}
public function testTwoKids()
{
$c = $this->em->getRepository('AppBundle:Category')->findOneBy(['name' => 'Hook']);
$cat = new \AppBundle\Entity\Category();
$cat->setName('Wet');
$this->em->persist($cat);
$c->addChild($cat);
$this->em->persist($c);
$this->em->flush();
/* this returns 1 */
$c2 = $this->em->getRepository('AppBundle:Category')->findOneBy(['name' => 'Hook']);
$children = $c2->getChildren();
$this->assertEquals(2, count($children));
/* this returns 2 */
// $id = $c2->getId();
// $children = $this->em->createQuery("SELECT c FROM AppBundle:Category c WHERE c.parent = $id")
// ->getResult();
// $this->assertEquals(2, count($children));
}
【问题讨论】:
-
我想你会发现这是你的测试中的一个错误。我不能完全理解正在发生的事情,但这可能是 Doctrine 结果缓存的问题。那里涉及到两个许多因素,以将其与 Doctrine 隔离开来。实体定义看起来不错。虽然
addChildren()方法有点奇怪。尝试在最后一次刷新后运行$this->em->clear();。 -
@Ryan 太好了!
$this->em->clear();解决了这个问题。作为解决方案发布,我很乐意接受。顺便说一句,addChildren()是使用doctrine:generate:entity的神器。
标签: php symfony doctrine-orm many-to-one