2015-04-12 5 views
0

У меня есть объект «Проект», который может иметь несколько преимуществ, в то время как выгода принадлежит только одному проекту: Мне кажется, что отношения от многих к одному - одному. Я последовал за указание 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(); 

Пособие получает должным образом сохранялось в БД.Это правильно ссылки к проекту:

enter image description here

Я тогда комментировать весь код в контроллере и просто выполнить:

$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)); 

Если я дамп $ проекта я получаю:

enter image description here

И, конечно, если я сброшу $ льготы, я получу это:

enter image description here

ответ

0

Вы не устанавливаете проект в своем классе преимуществ.

public function addBenefit(\AppBundle\Entity\Benefit $benefit) 
{ 
    $this->benefits[] = $benefit; 
    $benefit->setProject($this); // Add this 
    return $this; 
} 

Замечено, что я также изменил ваш аргумент из преимуществ в пользу, поскольку addBenefit имеет дело с одним объектом выгоды за раз.

+0

Спасибо @ Керад, я ошибочно доверял автоматическим геттерам и сеттерам. Это действительно решает проблему установки обеих ссылок вручную. Я просто устанавливаю parent-> child, и он автоматически создает дочерний элемент> родительский. Я также обнаружил, что включение cascade = "persist", когда я сохраняю родителя, он также сохраняет дочерний элемент, что приятно ... но все же я не получаю всех дочерних элементов родителя. Это похоже на то, что метод getBenefits() не реализован должным образом :( –

+0

Проверьте свою базу данных. Вероятно, у вас есть некоторые старые записи преимуществ, чей столбец project_id равен нулю. Удалить все и все должно идти вперед. Важно понимать, что сами сущности просто просто php-объекты и ничего не знают о сопоставлениях ORM, поэтому вам нужно убедиться, что отношения установлены должным образом.Это действительно работает.Я обещаю. Просто нужно перебраться через учебный горб. Руководство по доктрине полезно: http : //doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html – Cerad

+0

И не забудьте вызвать $ em-> flush() после добавления преимуществ (или внесения каких-либо изменений). – Cerad