2016-02-01 63 views
1

我想通过查询生成器构建查询。Symfony - Doctrine QueryBuilder生成错误的sql

$photosQuery = $photoRepository->createQueryBuilder('p') 
     ->join('AppBundle:User', 'u') 
     ->where('LOWER(p.title) LIKE :phrase OR LOWER(u.username) LIKE :phrase AND p.isActive = :isActive AND p.isModerated = :isModerated') 
     ->setParameter('phrase', '%'.strtolower($phrase).'%') 
     ->setParameter('isActive', true) 
     ->setParameter('isModerated', true) 
     ->getQuery(); 

它给了我

SELECT p0_.id AS id_0, 
     p0_.title AS title_1, 
     p0_.description AS description_2, 
     p0_.name AS name_3, 
     p0_.creation_date AS creation_date_4, 
     p0_.edit_date AS edit_date_5, 
     p0_.is_moderated AS is_moderated_6, 
     p0_.moderation_date AS moderation_date_7, 
     p0_.is_active AS is_active_8, 
     p0_.user_id AS user_id_9, 
     p0_.category_id AS category_id_10 
FROM photos p0_ 
INNER JOIN users u1_ ON (LOWER(p0_.title) LIKE ? 
         OR LOWER(u1_.username) LIKE ? 
         AND p0_.is_active = ? 
         AND p0_.is_moderated = ?) 

为什么我在加入ON()部分WHERE参数,而不是传统的WHERE

谢谢!

+0

尝试将您的连接更改为' - >连接('p.user','u')' –

+0

Jason,谢谢! – Tigran

+0

我增加了一个答案,更具体地解释了为什么会发生这种情况,以及将来如何解决这个问题,而不是犯同样的错误。 –

回答

1

Doctrine提供了一个低级别数据库连接的包装,它不必具有DQL中的所有功能。因此,它模拟一些功能(例如命名参数,或将数组参数拆分为多个单独的值)。

您在这里看到的是:在原始查询中,命名参数被转换为位置参数。尽管如此,Doctrine仍然知道映射是什么,并且在将查询和参数发送到服务器时能够正确地对它们进行排序。

0

因此,jbafford的答案解释了一些信息原则,但没有明确回答为什么使用ON而不是WHERE,这是由于一个常见的错误(我最近也提出这个错误)。

在您的查询,当您使用

->join('AppBundle:User', 'u') 

你只是告诉你需要加入对User表查询生成器,但它不知道具体要加入的user您的Photo实体的关联。你可能会认为 - 为什么这不会自动发生?那么,想象一下,如果您的桌面上还有另外一个关联到User实体的关联(可能是createdBy字段或类似关键字)。在这种情况下,学说不会知道你想要的联想。

所以,而是做正确的事是直接在您的加入协会,而不是一般的实体,像这样:

->join('p.user', 'u') 

,然后学说将处理其余部分。我实际上无法告诉你为什么它使用where()条件进行连接,除非它只是假设这就是你想要的,因为它需要知道如何连接

所以,请记住,当您加入一个您已经定义的关联时,请按照您的实体中所述的方式加入关联,而不是以直接SQL格式将其加入表格。

相关问题