У меня есть объект «Проект», который может иметь несколько преимуществ, в то время как выгода принадлежит только одному проекту: Мне кажется, что отношения от многих к одному - одному. Я последовал за указание hereSymfony2 Многие к одному - один к многим без таблицы соединения
Субъект Проекта:
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\ProjectRepository")
* @ORM\Table(name="projects")
*/
class Project
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\oneToMany(targetEntity="Benefit", mappedBy="project")
*/
protected $benefits;
/**
* Constructor
*/
public function __construct()
{
$this->benefits = new \Doctrine\Common\Collections\ArrayCollection();
}
// other stuff
/**
* Add benefits
*
* @param \AppBundle\Entity\Benefit $benefits
* @return Project
*/
public function addBenefit(\AppBundle\Entity\Benefit $benefits)
{
$this->benefits[] = $benefits;
return $this;
}
/**
* Remove benefits
*
* @param \AppBundle\Entity\Benefit $benefits
*/
public function removeBenefit(\AppBundle\Entity\Benefit $benefits)
{
$this->benefits->removeElement($benefits);
}
/**
* Get benefits
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getBenefits()
{
return $this->benefits;
}
}
Субъект выгоды:
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\BenefitRepository")
* @ORM\Table(name="benefits")
*/
class Benefit
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// Other relevant fields
/**
* @ORM\ManyToOne(targetEntity="Project", inversedBy="benefits")
*/
protected $project;
В моем контроллере я надеялся сделать:
$project = $em->getRepository('AppBundle:Project')->findOneById(3);
$benefit = new Benefit();
// set some fields for the new Benefit
$benefit->setProject($project);
$em->persist($benefit);
и я надеялся увидеть преимущества в виде коллекции в примкнуть сущность проекта делает:
$benefits = $project->getBenefits();
Но это не сработало, так что я сделал явно:
$project->addBenefit($benefit);
$em->persist($project);
$benefits = $project->getBenefits();
И я действительно вижу новый недавно созданный Benefit внутри коллекции внутри проекта. Проблема в том, что если я повторю это и добавлю новое преимущество в тот же проект, я просто получу последний. Конечно, если в той же части кода я создаю 2 преимущества и добавляю оба, у меня есть коллекция из 2, но это не то, что я хочу. На стороне Benefit все в порядке: каждый новый Benefit сохраняется, все они правильно указывают на тот же проект.
Что мне не хватает?
EDIT:
Вот шаги, которые я делаю/материал я проверил:
БД находится в синхронизации с текущими метаданными объекта. Обновленный объект Проект:
<?php
// src/AppBundle/Entity/Project.php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="AppBundle\Entity\ProjectRepository")
* @ORM\Table(name="projects")
*/
class Project
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\oneToMany(targetEntity="Benefit", mappedBy="project", cascade="persist")
*/
protected $benefits;
/**
* Constructor
*/
public function __construct()
{
$this->benefits = new \Doctrine\Common\Collections\ArrayCollection();
}
// Other irrelevant fields
/**
* Add benefits
*
* @param \AppBundle\Entity\Benefit $benefit
* @return Project
*/
public function addBenefit(\AppBundle\Entity\Benefit $benefit)
{
$this->benefits[] = $benefit;
$benefit->setProject($this);
return $this;
}
/**
* Remove benefits
*
* @param \AppBundle\Entity\Benefit $benefits
*/
public function removeBenefit(\AppBundle\Entity\Benefit $benefits)
{
$this->benefits->removeElement($benefits);
}
/**
* Get benefits
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getBenefits()
{
return $this->benefits;
}
}
Обратите внимание, что removeBenefit, вероятно, не правильно реализован, но на данный момент это не имеет значения.
Я очищаю таблицу преимуществ.
создать новую выгоду и приложить к Проекту:
$em = $this->getDoctrine()->getManager();
$project = $em->getRepository('AppBundle:Project')->findOneById(3);
$benefit = new Benefit();
$benefit->setName('Name of the benefit');
// here I set other irrelevant fields
$project->addBenefit($benefit);
$em->persist($project);
$em->flush();
Пособие получает должным образом сохранялось в БД.Это правильно ссылки к проекту:
Я тогда комментировать весь код в контроллере и просто выполнить:
$em = $this->getDoctrine()->getManager();
$project = $em->getRepository('AppBundle:Project')->findOneById(3);
$benefits = $project->getBenefits();
return $this->render('testBenefits.html.twig', array(
'benefits' => $benefits, 'project' => $project));
Если я дамп $ проекта я получаю:
И, конечно, если я сброшу $ льготы, я получу это:
Спасибо @ Керад, я ошибочно доверял автоматическим геттерам и сеттерам. Это действительно решает проблему установки обеих ссылок вручную. Я просто устанавливаю parent-> child, и он автоматически создает дочерний элемент> родительский. Я также обнаружил, что включение cascade = "persist", когда я сохраняю родителя, он также сохраняет дочерний элемент, что приятно ... но все же я не получаю всех дочерних элементов родителя. Это похоже на то, что метод getBenefits() не реализован должным образом :( –
Проверьте свою базу данных. Вероятно, у вас есть некоторые старые записи преимуществ, чей столбец project_id равен нулю. Удалить все и все должно идти вперед. Важно понимать, что сами сущности просто просто php-объекты и ничего не знают о сопоставлениях ORM, поэтому вам нужно убедиться, что отношения установлены должным образом.Это действительно работает.Я обещаю. Просто нужно перебраться через учебный горб. Руководство по доктрине полезно: http : //doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html – Cerad
И не забудьте вызвать $ em-> flush() после добавления преимуществ (или внесения каких-либо изменений). – Cerad