【问题标题】:Doctrine Symfony one-many not working but many-one isDoctrine Symfony one-many 不工作,但 many-one 是
【发布时间】:2013-08-13 21:01:16
【问题描述】:

好的,这是解决树木问题的真正木材。

我正在尝试使一对多对多一的实体结构正常工作。 我有三个实体

  • 项目(有 ID 和名称)
  • 研究员(有 ID 和姓名)
  • 项目研究员(有 ID、项目 ID、研究员 ID 和研究员在该项目中的角色)

所以它们的编码如下(使用注解)

namespace ons\Bundle\Geneapro\DataBundle\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
 * Project
 *
 * @ORM\Table(name="gpt_project")
 * @ORM\Entity
 */
class Project
{
    /**
     * @var string
     *
     * @ORM\Column(name="Name", type="string", nullable=false)
     */
    private $name;

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\OneToMany(targetEntity=" ResearcherProject", mappedBy="project")
     */
    private $researcherprojects;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->researcherprojects = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Project
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

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

    /**
     * Add researcherprojects
     *
     * @param ResearcherProject $researcherprojects
     * @return Project
     */
    public function addResearcherproject(ResearcherProject $researcherprojects)
    {
        $this->researcherprojects[] = $researcherprojects;
        return $this;
    }

    /**
     * Remove researcherprojects
     *
     * @param ResearcherProject $researcherprojects
     */
    public function removeResearcherproject(ResearcherProject $researcherprojects)
    {
        $this->researcherprojects->removeElement($researcherprojects);
    }

    /**
     * Get researcherprojects
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getResearcherprojects()
    {
        return $this->researcherprojects;
    }
}

研究员几乎一模一样

namespace ons\Bundle\Geneapro\DataBundle\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
 * Researcher
 *
 * @ORM\Table(name="gpt_researcher")
 * @ORM\Entity
 */
class Researcher
{
    /**
     * @var string
     *
     * @ORM\Column(name="Name", type="string", nullable=false)
     */
    private $name;

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\OneToMany(targetEntity=" ResearcherProject", mappedBy="researcher")
     */
    private $researcherprojects;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->researcherprojects = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Researcher
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

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

    /**
     * Add researcherprojects
     *
     * @param ResearcherProject $researcherprojects
     * @return Researcher
     */
    public function addResearcherproject(ResearcherProject $researcherprojects)
    {
        $this->researcherprojects[] = $researcherprojects;
        return $this;
    }

    /**
     * Remove researcherprojects
     *
     * @param ResearcherProject $researcherprojects
     */
    public function removeResearcherproject(ResearcherProject $researcherprojects)
    {
        $this->researcherprojects->removeElement($researcherprojects);
    }

    /**
     * Get researcherprojects
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getResearcherprojects()
    {
        return $this->researcherprojects;
    }
}

最后是 ResearcherProject

namespace ons\Bundle\Geneapro\DataBundle\Entity;
use Doctrine\ORM\Mapping as ORM;

/**
 * ResearcherProject
 *
 * @ORM\Table(name="gpt_researcher_project")
 * @ORM\Entity
 */
class ResearcherProject
{
    /**
     * @var string
     *
     * @ORM\Column(name="Role", type="string", nullable=false)
     */
    private $role;

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var Researcher
     *
     * @ORM\ManyToOne(targetEntity="Researcher", inversedBy="researcherprojects")
     */
    private $researcher;

    /**
     * @var Project
     *
     * @ORM\ManyToOne(targetEntity="Project", inversedBy="researcherprojects")
     */
    private $project;

    /**
     * Set role
     *
     * @param string $role
     * @return ResearcherProject
     */
    public function setRole($role)
    {
        $this->role = $role;
        return $this;
    }

    /**
     * Get role
     *
     * @return string 
     */
    public function getRole()
    {
        return $this->role;
    }

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

    /**
     * Set researcher
     *
     * @param Researcher $researcher
     * @return ResearcherProject
     */
    public function setResearcher(Researcher $researcher = null)
    {
        $this->researcher = $researcher;
        return $this;
    }

    /**
     * Get researcher
     *
     * @return Researcher 
     */
    public function getResearcher()
    {
        return $this->researcher;
    }

    /**
     * Set project
     *
     * @param Project $project
     * @return ResearcherProject
     */
    public function setProject(Project $project = null)
    {
        $this->project = $project;
        return $this;
    }

    /**
     * Get project
     *
     * @return Project 
     */
    public function getProject()
    {
        return $this->project;
    }
}

正如预期的那样,会产生以下 SQL

CREATE TABLE gpt_project (id INT AUTO_INCREMENT NOT NULL, Name VARCHAR(255) NOT NULL, Description VARCHAR(255) DEFAULT NULL, ClientData LONGTEXT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;

CREATE TABLE gpt_researcher (id INT AUTO_INCREMENT NOT NULL, Name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;

CREATE TABLE gpt_researcher_project (id INT AUTO_INCREMENT NOT NULL, researcher_id INT DEFAULT NULL, project_id INT DEFAULT NULL, Role VARCHAR(255) NOT NULL, INDEX IDX_5E15A9AEC7533BDE (researcher_id), INDEX IDX_5E15A9AE166D1F9C (project_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;

ALTER TABLE gpt_researcher_project ADD CONSTRAINT FK_5E15A9AEC7533BDE FOREIGN KEY (researcher_id) REFERENCES gpt_researcher (id);

ALTER TABLE gpt_researcher_project ADD CONSTRAINT FK_5E15A9AE166D1F9C FOREIGN KEY (project_id) REFERENCES gpt_project (id);

到目前为止一切顺利,我现在使用 Behat 来编写我的场景,并且我定义了以下功能。

Feature: ResearcherProject
  In order to track who did research
  As the Data Bundle
  I need to be able to create and manage ResearcherProjects

Background:
    Given there is no "ResearcherProject" in database
    And there is no "Project" in database
    And there is no "Researcher" in database

Scenario: A ResearcherProject joins Researchers to Projects
    When I create a Project "New Project"  
    And I create a Researcher "Researcher" 
    And I add Researcher "Researcher" to Project "New Project" as "Lead"    
    Then Researcher Project "1" joins "Researcher" to Project "New Project" as "Lead"    
    And Project "New Project" is Researched By "1" Researcher 
    And Researcher "Researcher" Researches "1" Project

数据很好地加载到数据库中,并且研究人员项目的测试将项目链接到角色中的研究人员有效,但随后发生以下情况

01. Failed asserting that actual size 0 matches expected size 1. 
    In step `And Project "New Project" is Researched By "1" Researcher'.

进行测试的两个函数是

/**
 * @Then /^Researcher Project "([^"]*)" joins "([^"]*)" to Project "([^"]*)" as "([^"]*)"$/
 */
public function researcherProjectJoinsToProjectAs($ResearcherProjectID, $ResearcherName, $ProjectName, $Role)
{
    $rp=$this->getEntityByID("ResearcherProject", $ResearcherProjectID);
    assertEquals($ResearcherProjectID, $rp->getID());
    assertEquals($ResearcherName,$rp->getResearcher()->getName());
    assertEquals($ProjectName,$rp->getProject()->getName());                
    assertEquals($Role,$rp->getRole());
}

/**
 * @Then /^Project "([^"]*)" is Researched By "([^"]*)" Researcher$/
 */
public function projectIsResearchedByResearcher($ProjectName, $expectedCount)
{        
    $project=$this->getEntityByName("Project", $ProjectName);
    assertCount($expectedCount*1, $project->getResearcherprojects());
}

GetEntityByNameGetEntityByID 言行一致。

我做错了什么,为什么我可以由内而外工作,却不能由外而内? 这已经困扰我两天了,所以欢迎任何帮助,我相信这真的很简单,但它超出了我的能力。

编辑

所以我想我可以开始看到树了,但是现在问题略有不同! 这应该是一个无头包,所以我没有提供任何视图或控制器。添加树枝模板并运行它会弹出链接。

所以它一定是导致它的测试中的行为。

【问题讨论】:

  • 如果问题只是在测试过程中,那更多的是Behat的问题,不是吗?

标签: symfony doctrine one-to-many many-to-one behat


【解决方案1】:
assertEquals($expectedCount*1, $project->getResearcherprojects());

这个$project->getResearcherprojects() 返回一个ResearcherProject 的ArrayCollection。如果你想计算它们,你必须这样做:

assertEquals($expectedCount*1, $project->getResearcherprojects()->count());

【讨论】:

  • 如果我使用的是 assertEquals(),那将是真的,assertCount() 会为你“计数”。
  • 为您更正了答案。很确定 assertCount() 需要一个数组,而不是实现 Collection 和 Selectable 的 ArrayCollection。
  • 不确定幕后发生了什么转换,但assertCount($expectedCount*1, $project->getResearcherprojects()); 完美地工作数据在那里,如我的回答中所述。因此,进行您建议的更改将无效。
【解决方案2】:

好的,

有了 twig 方法之后,我想知道如果我只是从数据库中提取它是否会起作用,所以我将场景更改为

Feature: ResearcherProject
  In order to track who did research
  As the Data Bundle
  I need to be able to create and manage Researchers


Scenario: A ResearcherProject joins Researchers to Projects
    Then Researcher Project "1" joins "Researcher" to Project "New Project" as "Lead"    
    And Project "New Project" is Researched By "1" Researcher 
    And Researcher "Researcher" Researches "1" Project 

而且宾果游戏都通过了,所以它看起来像是一个缓存问题。实体管理器显然正在返回它捕获的我的项目和研究员的版本,它们还没有更新

所以问题就在这里......

/**
 * @Given /^I add Researcher "([^"]*)" to Project "([^"]*)" as "([^"]*)"$/
 */
public function iAddResearcherToProjectAs($ResearcherName, $ProjectName, $Role)
{

    $em = $this->getEntityManager();


    //Get Researcher
    $researcher=$em->getRepository('onsGeneaproDataBundle:Researcher')
                   ->findOneByName($ResearcherName);
    //Get Project
    $project=$em->getRepository('onsGeneaproDataBundle:Project')
                ->findOneByName($ProjectName);

    $researcherproject = new \ons\Bundle\Geneapro\DataBundle\Entity\ResearcherProject();
    $researcherproject->setRole($Role);
    $researcherproject->setProject($project);        
    $researcherproject->setResearcher($researcher);

//*** The following Two Lines make it work ***//
    $project->addResearcherproject($researcherproject);//Why dose this not happen automaticaly?
    $researcher->addResearcherproject($researcherproject);//Why dose this not happen automaticaly?
//*** ***//

    $em->persist($researcherproject);
    $em->flush();
}

如果我进行反向更新并将 ResearcherProject 添加到 Researcher 和 Project 中,那么所有测试都会通过。

但这引出了以下问题

  1. 为什么项目和研究人员不接收更新?
  2. 或如何在更新实体后强制实体管理器清除其缓存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多