Экспериментируя с самоссылающейся сущностью 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));
}
Попробуйте запустить $this->em->clear()
после вашего последнего сброса. Это может быть вызвано кэшированием менеджера сущностей Doctrine или результатом кэширования.
Других решений пока нет …