Symfony 使用 "NOT IN" 连接 DQL 表达式
Symfony joining DQL expressions with "NOT IN"
我正在使用 Symfony2,我正在尝试获取一组与指定客户端无关的语言。
我有一个 Client
表示客户端的实体,ClientLanguage
具有以下结构:
id_menu_language
主键
language
与语言实体的关联
client
与客户实体的关联
sequence
表示语言的显示顺序(此处未使用)
和Language
实体。
要获取与客户端无关的一组语言,我想按以下方式进行:
- 获取客户端已经关联的语言(我在
$clientLanguagesDQL
变量中获取正确的 DQL)
- 检索所有可用语言的列表
- 从该列表中排除所有已经关联到客户端的语言(通过使用 NOT IN (...) )。
这是我写的函数来实现:
<?php
namespace AppBundle\Repository;
use AppBundle\Entity\Client;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
class ClientRepository extends EntityRepository
{
/**
* @param $client Client to check
* @return array
*/
public function getLanguagesNotAssociatedToClient($client)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$clientLanguagesDQL = $qb
->select('lang')
->from('AppBundle:Language', 'lang')
->join('AppBundle:ClientLanguage', 'languages_assoc', Join::WITH, 'languages_assoc.language = lang')
->join('AppBundle:Client', 'client', Join::WITH, 'languages_assoc.client = client')
->where('client.idClient = :client_id')
->getQuery()
->getDQL();
$languages = $qb->select('language')
->from('AppBundle:Language', 'language')
->where($qb->expr()->notIn('language', $clientLanguagesDQL))
->setParameter('client_id', $client->getIdClient())
->getQuery()
->getResult();
return $languages;
}
}
然而,当我 运行 这个时,Symfony 抱怨 : [Semantical Error] line 0, col 293 near 'lang INNER JOIN': Error: 'lang' is already defined.
它也告诉我有一个 QueryException
,它向我显示了以下查询:
SELECT language
FROM AppBundle:Language lang
INNER JOIN AppBundle:ClientLanguage languages_assoc
WITH languages_assoc.language = lang
INNER JOIN AppBundle:Client client
WITH languages_assoc.client = client, AppBundle:Language language WHERE language NOT IN(
SELECT lang
FROM AppBundle:Language lang
INNER JOIN AppBundle:ClientLanguage languages_assoc
WITH languages_assoc.language = lang
INNER JOIN AppBundle:Client client
WITH languages_assoc.client = client
WHERE client.idClient = :client_id
)
而这绝对不是我想做的。为什么出现 AppBundle:ClientLanguage
和 AppBundle:Client
的两个连接?我只在我的第一个子查询中使用这个关联。
如果有帮助,当我运行这个:
$clientLanguagesDQL = $qb
->select('lang')
->from('AppBundle:Language', 'lang')
->join('AppBundle:ClientLanguage', 'languages_assoc', Join::WITH, 'languages_assoc.language = lang')
->join('AppBundle:Client', 'client', Join::WITH, 'languages_assoc.client = client')
->where('client.idClient = :client_id')
->getQuery()
->getDQL();
这是存储在$clientLanguageDQL
中返回的DQL:
SELECT lang
FROM AppBundle:Language lang
INNER JOIN AppBundle:ClientLanguage languages_assoc
WITH languages_assoc.language = lang
INNER JOIN AppBundle:Client client
WITH languages_assoc.client = client
WHERE client.idClient = :client_id
这个查询有什么问题?
我的错误非常愚蠢,我所要做的就是为每个查询创建一个新的查询构建器,而不是重复使用第一个:
$qb1 = $this->getEntityManager()->createQueryBuilder();
$clientLanguagesDQL = $qb1
->select('lang')
->from('AppBundle:Language', 'lang')
->join('AppBundle:ClientLanguage', 'languages_assoc', Join::WITH, 'languages_assoc.language = lang')
->join('AppBundle:Client', 'client', Join::WITH, 'languages_assoc.client = client')
->where('client.idClient = :client_id')
->getQuery()
->getDQL();
$qb2 = $this->getEntityManager()->createQueryBuilder();
$languages = $qb2->select('language')
->from('AppBundle:Language', 'language')
->where($qb2->expr()->notIn('language', $clientLanguagesDQL))
->setParameter('client_id', $client->getIdClient())
->getQuery()
->getResult();
return $languages;
我正在使用 Symfony2,我正在尝试获取一组与指定客户端无关的语言。
我有一个 Client
表示客户端的实体,ClientLanguage
具有以下结构:
id_menu_language
主键language
与语言实体的关联client
与客户实体的关联sequence
表示语言的显示顺序(此处未使用)
和Language
实体。
要获取与客户端无关的一组语言,我想按以下方式进行:
- 获取客户端已经关联的语言(我在
$clientLanguagesDQL
变量中获取正确的 DQL) - 检索所有可用语言的列表
- 从该列表中排除所有已经关联到客户端的语言(通过使用 NOT IN (...) )。
这是我写的函数来实现:
<?php
namespace AppBundle\Repository;
use AppBundle\Entity\Client;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
class ClientRepository extends EntityRepository
{
/**
* @param $client Client to check
* @return array
*/
public function getLanguagesNotAssociatedToClient($client)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$clientLanguagesDQL = $qb
->select('lang')
->from('AppBundle:Language', 'lang')
->join('AppBundle:ClientLanguage', 'languages_assoc', Join::WITH, 'languages_assoc.language = lang')
->join('AppBundle:Client', 'client', Join::WITH, 'languages_assoc.client = client')
->where('client.idClient = :client_id')
->getQuery()
->getDQL();
$languages = $qb->select('language')
->from('AppBundle:Language', 'language')
->where($qb->expr()->notIn('language', $clientLanguagesDQL))
->setParameter('client_id', $client->getIdClient())
->getQuery()
->getResult();
return $languages;
}
}
然而,当我 运行 这个时,Symfony 抱怨 : [Semantical Error] line 0, col 293 near 'lang INNER JOIN': Error: 'lang' is already defined.
它也告诉我有一个 QueryException
,它向我显示了以下查询:
SELECT language
FROM AppBundle:Language lang
INNER JOIN AppBundle:ClientLanguage languages_assoc
WITH languages_assoc.language = lang
INNER JOIN AppBundle:Client client
WITH languages_assoc.client = client, AppBundle:Language language WHERE language NOT IN(
SELECT lang
FROM AppBundle:Language lang
INNER JOIN AppBundle:ClientLanguage languages_assoc
WITH languages_assoc.language = lang
INNER JOIN AppBundle:Client client
WITH languages_assoc.client = client
WHERE client.idClient = :client_id
)
而这绝对不是我想做的。为什么出现 AppBundle:ClientLanguage
和 AppBundle:Client
的两个连接?我只在我的第一个子查询中使用这个关联。
如果有帮助,当我运行这个:
$clientLanguagesDQL = $qb
->select('lang')
->from('AppBundle:Language', 'lang')
->join('AppBundle:ClientLanguage', 'languages_assoc', Join::WITH, 'languages_assoc.language = lang')
->join('AppBundle:Client', 'client', Join::WITH, 'languages_assoc.client = client')
->where('client.idClient = :client_id')
->getQuery()
->getDQL();
这是存储在$clientLanguageDQL
中返回的DQL:
SELECT lang
FROM AppBundle:Language lang
INNER JOIN AppBundle:ClientLanguage languages_assoc
WITH languages_assoc.language = lang
INNER JOIN AppBundle:Client client
WITH languages_assoc.client = client
WHERE client.idClient = :client_id
这个查询有什么问题?
我的错误非常愚蠢,我所要做的就是为每个查询创建一个新的查询构建器,而不是重复使用第一个:
$qb1 = $this->getEntityManager()->createQueryBuilder();
$clientLanguagesDQL = $qb1
->select('lang')
->from('AppBundle:Language', 'lang')
->join('AppBundle:ClientLanguage', 'languages_assoc', Join::WITH, 'languages_assoc.language = lang')
->join('AppBundle:Client', 'client', Join::WITH, 'languages_assoc.client = client')
->where('client.idClient = :client_id')
->getQuery()
->getDQL();
$qb2 = $this->getEntityManager()->createQueryBuilder();
$languages = $qb2->select('language')
->from('AppBundle:Language', 'language')
->where($qb2->expr()->notIn('language', $clientLanguagesDQL))
->setParameter('client_id', $client->getIdClient())
->getQuery()
->getResult();
return $languages;