doctrine查询构建器连接添加表两次

时间:2013-04-27 21:27:09

标签: php symfony doctrine left-join

在底部更新:

我正在尝试做两个表之间的简单连接。我有一个Gig表和一个Venue表,用于我使用Symfony2(2.2)构建的简单乐队网站。这是我第一次使用Symfony2和doctrine,所以我可能完全走错了方向。我已经使用DataFixtures创建并填充了表,并验证了ID关系是否正确。我得到的问题是,生成的DQL查询在FROM部分中引用了两次Gig表,这导致我返回同一记录的多个实例而不是我期望的x个记录。我不知道我做错了什么。此外,可能有一种更简单的方法,但我正在探索我的所有选择,因为我在构建网站的过程中自学Symfony2。

Gig表包含一个venue_id,指向Venue表,该表在Gig实体中定义为ManyToOne关系(如下所示)。使用doctrine findAll似乎一切正常,并且Gig实体中的Venue类正确填充。我正在尝试创建一些最新Gigs的平面视图,以便在首页上显示,所以我想我会尝试使用Join并仅包含我需要的字段。

这是存储库查询:

public function getGigsWithLimit($maxGigs)
{
    $qb = $this->createQueryBuilder('b')
        ->select('
            g.gigDate,
            g.startTime,
            g.endTime,
            g.message1 as gig_message1,
            g.message2 as gig_message2,
            g.url,
            v.name,
            v.address1,
            v.address2,
            v.city,
            v.state,
            v.zip,
            v.phone,
            v.url as venue_url,
            v.message1 as venue_message1,
            v.message2 as venue_message2,
            v.message3 as venue_message3'
        )
        ->from('WieldingBassBundle:Gig', 'g')
        ->leftJoin('g.venue', 'v')
        ->orderBy('g.gigDate', 'DESC')
        ->setMaxResults($maxGigs);

    return $qb->getQuery()->getResult();

}

这是它创建的DQL:

SELECT 
  g0_.id AS id0, 
  g0_.gig_date AS gig_date1, 
  g0_.start_time AS start_time2, 
  g0_.end_time AS end_time3, 
  g0_.message1 AS message14, 
  g0_.message2 AS message25, 
  g0_.url AS url6, 
  v1_.name AS name7, 
  v1_.address1 AS address18, 
  v1_.address2 AS address29, 
  v1_.city AS city10, 
  v1_.state AS state11, 
  v1_.zip AS zip12, 
  v1_.phone AS phone13, 
  v1_.url AS url14, 
  v1_.message1 AS message115, 
  v1_.message2 AS message216, 
  v1_.message3 AS message317 
FROM 
  Gig g2_, 
  Gig g0_ 
LEFT JOIN 
  Venue v1_ ON g0_.venue_id = v1_.id 
LIMIT 
  6

Gig g2 _ 是我的问题。如果我删除它并执行查询,一切都按预期进行。我不知道是什么产生的。

第一个表Gigs Entity看起来像这样(我要忘掉getter和setter):

/**
 * Gig
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Wielding\BassBundle\Entity\GigRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Gig
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="gig_date", type="date")
 */
private $gigDate;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="start_time", type="datetime")
 */
private $startTime;

/**
 * @var \DateTime
 *
 * @ORM\Column(name="end_time", type="datetime")
 */
private $endTime;

/**
 * @var string
 *
 * @ORM\Column(name="message1", type="string", length=50, nullable=true)
 */
private $message1;

/**
 * @var string
 *
 * @ORM\Column(name="message2", type="string", length=50, nullable=true)
 */
private $message2;

/**
 * @var string
 *
 * @ORM\Column(name="url", type="string", length=128, nullable=true)
 */
private $url;

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

/**
 * @ORM\Column(type="datetime")
 */
protected $created;

/**
 * @ORM\Column(type="datetime")
 */
protected $updated;


/**
 * @ORM\ManyToOne(targetEntity="Venue", cascade="persist")
 * @ORM\JoinColumn(name="venue_id", referencedColumnName="id")
 */
protected $venue;

Venue表很简单,没有定义任何关系,所以除非要求,否则我会将其遗漏。

有什么想法吗?谢谢你的帮助。

安德鲁

我删除了除重新创建问题之外的所有内容,这就是我留下的内容:

我将存储库方法简化为:

public function getGigsWithLimit2($maxGigs)
{
    $qb = $this->createQueryBuilder('a')
        ->select('g.id')
        ->from('WieldingBassBundle:Gig', 'g')
        ->setMaxResults($maxGigs);

    return $qb->getQuery()->getResult();
}

现在生成:

SELECT 
  g0_.id AS id0 
FROM 
  Gig g1_, 
  Gig g0_ 
LIMIT 
  6

再次出现了gg gg_问题。我从Symfony分析器中获得了“解释查询”,它显示:

id  select_type table   type    possible_keys   key key_len ref rows        Extra
1   SIMPLE  g1_ index       IDX_ED7D664240A73EBA    4       9     Using index
1   SIMPLE  g0_ index       IDX_ED7D664240A73EBA    4       9    Using index; Using join buffer

我不会假装知道这意味着什么,但它会显示两个表条目,其中包含有关如何使用它的不同信息。

3 个答案:

答案 0 :(得分:0)

如果您已经拥有包含外键的“场地”,那么“venueId”的使用是什么?

答案 1 :(得分:0)

我发现了问题。我不习惯Doctrine并且在不需要它的存储库中使用 - > from,因为实体通过注释自动关联。我之前的查询是在控制器而不是存储库中,所以 - > from是必要的。

答案 2 :(得分:0)

您正在尝试执行SQL。学说不同。您的查询将获取每个字段。 Doctrine更喜欢获取实体。我想你可能想要这个:

public function getGigsWithLimit($maxGigs)
{
    $qb = $this->createQueryBuilder('g')
        ->leftJoin('g.venue', 'v')
        ->orderBy('g.gigDate', 'DESC')
        ->setMaxResults($maxGigs);

    return $qb->getQuery()->getResult();

}

返回结果是一个实体列表,您可以直接调用所有特定方法。如果你想要部分对象,你仍然可以指定带有教义的字段,但我发现获取整个实体的常规方法可以满足我的大部分需求。

这是一个与SQL完全不同的范例,需要一些时间来习惯。