【问题标题】:Symfony Doctrine joining a one to many relationshipSymfony 原则加入一对多关系
【发布时间】:2014-04-17 02:46:17
【问题描述】:

我想将两个表连接在一起,以便在一次搜索中检索所有实体。我有一对多的关系:绝地和成员。一个成员组可以有许多绝地武士。我想制作一个表单来按一个实体搜索并将所有信息作为一个整体显示。

示例:按指定颜色搜索绝地 -> 检索姓名、年龄、性别、颜色和等级。

Jedi.php:

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

/**
 * @var string
 *
 * @ORM\Column(name="name", type="string", length=255)
 */
private $name;

/**
 * @var integer
 *
 * @ORM\Column(name="age", type="integer")
 */
private $age;

/**
 * @var string
 *
 * @ORM\Column(name="gender", type="string", length=255)
 */
private $gender;

/**
 *
 * @ORM\ManyToOne(targetEntity="Member", inversedBy="jedi")
 * @ORM\JoinColumn(name="member", referencedColumnName="id")
 */
private $member;

会员.php:

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

/**
 * @var string
 *
 * @ORM\Column(name="rank", type="string", length=255)
 */
private $rank;

/**
 * @var string
 *
 * @ORM\Column(name="color", type="string", length=255)
 */
private $color;

/**
 * @var integer
 * @ORM\OneToMany(targetEntity="Jedi", mappedBy="member")
 *
 */
protected $jedi;

在我的 JediRepository.php 中:

class JediRepository extends EntityRepository
{

public function findJediByColor($color) {

    $query = $this->getEntityManager()
        ->createQuery(
            'SELECT color, rank
             FROM YodaBundle:Member member
             JOIN member.jedi 
             WHERE member.color = :color'
        )->setParameter('color', $color);

    try {
        return $query->getSingleResult();
    } catch (\Doctrine\ORM\NoResultException $e) {
        return null;
    }

 }
}

现在我很确定我的查询连接语句可能全错了,我对如何使用它感到很困惑。任何帮助将不胜感激!

【问题讨论】:

  • 我承认对教义不太熟悉,但如果桌子是YodaBundle:Member,绝地桌子不是YodaBundle:Jedi吗?
  • @steven 你的意思是在查询中?

标签: php symfony join doctrine-orm


【解决方案1】:

您的代码有误。您的查询检索了许多行,但您将其作为单行 (getSingleResult())。正如您在文档中看到的 (http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#query-result-formats) getSingleResult() 将在每次满足您的查询时抛出异常。 此外,如果您需要实体的所有列,则无需在查询中指定每一列。您可以指定要检索的实体:

$query = $this->getEntityManager()
    ->createQuery(
        'SELECT member, jedi
         FROM YodaBundle:Member member
         JOIN member.jedi 
         WHERE member.color = :color'
    )->setParameter('color', $color);

try {
    return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
    return null;
}

请注意,在 Select 语句中我使用了 member 和 jedi。在这种情况下,Doctrine 将使用渴望连接(一个查询中的所有数据)。如果您只需要选择成员并且对于其中一些成员检索 jedis,您可以在查询的 Select 部分中省略 jedi。

【讨论】:

    【解决方案2】:

    首先,您应该将函数 findJediByColor 移动到成员存储库,因为主表是成员而不是绝地。

    其次,您应该像下面的示例一样使用 queryBuilder(在 MemberRepository 中)。这将返回一个带有数组 od Jedi's 的成员对象。请注意,我使用“member_”作为主要别名。不知何故,“member”不起作用(我现在不知道为什么)。

    public function findJediByColor($color) {
    
        $query = $this->createQueryBuilder('member_')
            ->where('member_.color = :color')
            ->join('member_.jedi', 'jedi')
            ->setParameter('color', $color)
            ->getQuery();
    
        try {
            return $query->getResult();
        } catch (\Doctrine\ORM\NoResultException $e) {
            return null;
        }
    
    }
    

    如果您真的想对该查询使用 DQL,它应该如下所示:

        $query = $this->getEntityManager()
            ->createQuery(
                'SELECT member_.color, member_.rank, jedi.name
                FROM YodaBundle:Member member_
                JOIN member_.jedi jedi
                WHERE member_.color = :color'
            )->setParameter('color', $color);
    

    【讨论】:

      【解决方案3】:

      您不必创建具体的请求来执行此类操作。 它可以简单地完成:

      1. 在您的 oneToMany 实体定义中使用 Eager loading

        /**
         * @var integer
         * @ORM\OneToMany(targetEntity="Jedi", mappedBy="member",fetch="EAGER")
         *
         */
         protected $jedi;
        
      2. 在 Jedi 存储库中删除您的 public function findJediByColor($color) {

      3. 直接在控制器中使用magic function 存储库,例如:

        $this->getDoctrine()
        ->getRepository('YourBundle:Member')
        ->findByColour($colour);
        

        $this->getDoctrine()
        ->getRepository('YourBundle:Member')
        ->findByRank($rank);
        

        $this->getDoctrine()
        ->getRepository('YourBundle:Member')
        ->findByJedi($jedi);
        

        或有多个条件

        $this->getDoctrine()
        ->getRepository('YourBundle:Member')
        ->findBy(array('colour' => $colour, 'rank' => $rank));
        

      【讨论】:

        猜你喜欢
        • 2022-01-22
        • 1970-01-01
        • 2016-08-21
        • 2015-04-05
        • 1970-01-01
        • 1970-01-01
        • 2015-08-12
        • 1970-01-01
        相关资源
        最近更新 更多