Symfony 2 与 Doctrine 中的一对多关系

Posted

技术标签:

【中文标题】Symfony 2 与 Doctrine 中的一对多关系【英文标题】:One-To-Many Relation in Symfony 2 with Doctrine 【发布时间】:2013-06-19 08:18:06 【问题描述】:

我已经在 Stack Overflow 和网络上的其他地方查看了大量的问题/答案,但找不到解决这个问题的方法。

在我解释问题之前,我有:

剥离我的实体,使它们只有最少的属性和方法 已清除学说查询缓存/元数据缓存 删除并重新创建架构 检查了我的拼写

我有以下两个实体:

<?php
namespace Docker\ApiBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Source

  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\Column(type="integer")
   * @ORM\ManyToOne(targetEntity="Project",inversedBy="sources")
   * @ORM\JoinColumn(referencedColumnName="id")
   */
  private $project;




<?php
namespace Docker\ApiBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Project

  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\OneToMany(targetEntity="Source", mappedBy="project")
   */
  private $sources;

  public function __construct() 
    $this->sources = new ArrayCollection();
  

  public function getSources() 
    return $this->sources;
  

所以许多“来源”可以属于一个“项目”。

在我的控制器中,我有:

$em = $this->getDoctrine()->getManager();
$project = $em->find('Docker\ApiBundle\Entity\Project', 1);
$sources = $project->getSources()->toArray();

我尝试了很多东西,但我总是得到:

Notice: Undefined index: project in /.../www/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php line 1577

就像我说的,我知道有很多关于这个问题的问题,但没有一个被接受的答案能解决我的问题。

这一切对于使用 Doctrine2 来说都是非常基础的,所以不确定我做错了什么——这可能是非常明显的事情。

任何帮助将不胜感激。

【问题讨论】:

$project var 不是 null 吗?或者在做时 ->getSources()->toArray();崩溃了? $project var 不为空,是的 - 当我在控制器中执行 $sources = $project-&gt;getSources()-&gt;toArray(); 时导致异常。如果我把它拿出来就可以了。 【参考方案1】:

你有:

/**
* @ORM\Column(type="integer")
* @ORM\ManyToOne(targetEntity="Project",inversedBy="sources")
* @ORM\JoinColumn(referencedColumnName="id")
*/
private $project;

删除:

@ORM\Column(type="integer")

来自注释。

【讨论】:

啊哈!这就对了。这也很有意义。谢谢。【参考方案2】:

如果这正是您的代码,我在您的 Project 类中看不到命名空间。尝试添加命名空间行“命名空间 Docker\ApiBundle\Entity;”。 如果这是同一个文件夹,则不需要“使用”,但如果它是其他捆绑包或文件夹的一部分,请尝试输入“使用 Docker\ApiBundle\Entity\Project;”之类的行 在您的 Source 类中。我希望它有帮助..

否则:

<?php
namespace Azimut\ApiBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class Source

  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  private $name;


  /**
   * @ORM\Column(type="integer")
   * @ORM\ManyToOne(targetEntity="Azimut\ApiBundle\Entity\Project", inversedBy="sources")
   * @ORM\JoinColumn(onDelete="CASCADE")
   */
  private $project;


/**
 * Get id
 *
 * @return integer 
 */
public function getId()

    return $this->id;


/**
 * Set project
 *
 * @param integer $project
 * @return Source
 */
public function setProject($project)

    $this->project = $project;

    return $this;


/**
 * Get project
 *
 * @return integer 
 */
public function getProject()

    return $this->project;




<?php
namespace Azimut\ApiBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity
 */
class Project

  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  private $id;

  /**
   * @ORM\OneToMany(targetEntity="Azimut\ApiBundle\Entity\Source", mappedBy="object", cascade="all")
   */
  private $sources;

  public function __construct() 
    $this->sources = new ArrayCollection();
  

  public function getSources() 
    return $this->sources;
  

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    
        return $this->id;
    

/**
 * Add sources
 *
 * @param \Azimut\ApiBundle\Entity\Source $sources
 * @return Project
 */
public function addSource(\Azimut\ApiBundle\Entity\Source $sources)

    $this->sources[] = $sources;

    return $this;


/**
 * Remove sources
 *
 * @param \Azimut\ApiBundle\Entity\Source $sources
 */
public function removeSource(\Azimut\ApiBundle\Entity\Source $sources)

    $this->sources->removeElement($sources);


和控制器的一小部分: 公共函数 helloAction()


        $id = 1;
        $em = $this->getDoctrine()->getManager();
        $project = $em->getRepository('Azimut\ApiBundle\Entity\Project')->find($id);

        $source1 = $em->getRepository('Azimut\ApiBundle\Entity\Source')->find(3);
        $source2 = $em->getRepository('Azimut\ApiBundle\Entity\Source')->find(5);
        $project->addSource($source1);
        $sources = array();
        $sources = $project->getSources();
        var_dump($sources);
        return ....

这对我来说很好用。

【讨论】:

好地方 - 但只是帖子的格式不完全存在。我已对其进行了更新,以便显示名称空间。 好的——太好了——对我有用。但是...我猜想像 Doctrine 这样的库的一些问题是 magic。它似乎为您做了很多,所以我想如果我已经用我的项目的源填充数据库,那么我不需要使用 addSource 将它们添加到项目实体中?我猜我可以做一些 postLoad 事件回调来自动执行此操作,但我不是 100% 确定(考虑到它所做的其他事情)为什么我需要这样做。事实上,我不知道为什么我什至需要首先设置注释? 感谢您为此付出的辛勤工作,但@zelkjo 的回答是正确的。在您的回复中,我必须将源添加到项目中,在 Zeljok 的项目中,如果数据库是预先填充的,那么它会返回我所期望的,即填充的源实体。我为你 +1 了 - 再次感谢。 这取决于你想做什么,我手动添加了一些来源和项目,因为我以前没有任何这样的实体。我以为您想将其保留为整数,并尝试使用尽可能多的代码。注释用于映射您数据库中的对象。您可以使用注释、yml 或 xml 来设置您的数据库。如果您对注释不够自信,请使用其他解决方案。

以上是关于Symfony 2 与 Doctrine 中的一对多关系的主要内容,如果未能解决你的问题,请参考以下文章

Symfony2 和 Doctrine:一对多关系

Symfony Doctrine:一对多关系正在删除父实体

如何通过 SonataAdminBundle (Symfony) 管理 Doctrine ORM 类表继承?

级联持久性不工作(Doctrine ORM + Symfony 2)

Symfony/Doctrine 类表继承和外键作为主键

Symfony2 项目中的 Doctrine2 映射问题