Symfony2多对一-无联接表的一对多

Symfony2多对一-无联接表的一对多,symfony,doctrine-orm,one-to-many,many-to-one,Symfony,Doctrine Orm,One To Many,Many To One,我有一个“项目”实体,它可以有几个好处,而一个好处只属于一个项目: 对我来说,这似乎是一种多对一-一对多的关系。 我遵循指示 项目实体为: /** * @ORM\Entity(repositoryClass="AppBundle\Entity\ProjectRepository") * @ORM\Table(name="projects") */ class Project { /** * @ORM\Column(type="integer") * @ORM\I

我有一个“项目”实体,它可以有几个好处,而一个好处只属于一个项目: 对我来说,这似乎是一种多对一-一对多的关系。 我遵循指示

项目实体为:

/**
 * @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;
<?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;
    }
}
受益实体为:

/**
 * @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;
<?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;
    }
}
在我的控制器中,我希望执行以下操作:

$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();
我确实看到了新的,在项目内部集合中新创建的好处。问题是,如果我重新运行它并为同一个项目添加新的好处,我只会得到最后一个。当然,如果在代码的同一部分中我创建了两个优点并同时添加了这两个优点,那么我有一个2个的集合,但这不是我想要的。在收益方面,一切都正常:每个新的收益都被持久化,它们都正确地指向同一个项目

我错过了什么

编辑:

以下是我制作/检查的步骤:

数据库与当前实体元数据同步。 更新后的项目实体为:

/**
 * @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;
<?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;
    }
}
这种好处会被正确地持久化到DB中。它正确地链接到项目:

然后,我对控制器中的所有代码进行注释,只需执行以下操作:

$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));
如果我放弃$project,我会得到:

当然,如果我放弃$benefits,我会得到:


您没有在福利类别中设置项目

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

注意到我还将您的论点从一个优点改为另一个优点,因为addBenefit一次只处理一个优点对象。

Thank you@Cerad,我错误地信任自动获取者和设置者。这确实解决了必须手动设置两个引用的问题。我只是设置了parent->child,它会自动创建child->parent。我还发现,当我保存父对象时,包括cascade=“persist”也会保存子对象,这很好……但我仍然没有得到父对象的所有子对象。这就像getBenefits()方法没有正确实现一样:(检查您的数据库。您可能有一些旧的福利记录,其project_id列为空。删除这些记录,所有这些记录都将顺利进行。了解这些实体本身只是普通的php对象,并且对ORM映射一无所知,这一点很重要。因此,您需要确保关系设置正确。这是非常重要的真的有用。我保证。只需要克服学习困难。原则手册很有帮助:在添加好处(或进行任何其他更改)后,不要忘记调用$em->flush().I每次进行更改时都清理数据库。效益表为空。我检索项目。我创建效益并将其添加到项目中。我保留项目并刷新。一切正常(效益在数据库中,项目id设置正确)。如果我现在调用getBenefits,我有一个空数组集合:(.问题就在这里。就像只有添加一个或多个好处并直接调用getBenefits时getBenefits才起作用(在运行时,不是从DB获取数据)