在底部更新:
我正在尝试做两个表之间的简单连接。我有一个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
我不会假装知道这意味着什么,但它会显示两个表条目,其中包含有关如何使用它的不同信息。
答案 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完全不同的范例,需要一些时间来习惯。