我想使用
left join
从“页面”到“术语”进行
NOT IN
实体
/**
* @ORM\Entity(repositoryClass="AppBundle\Repository\PageRepository")
* @ExclusionPolicy("all")
*/
class Page
{
/**
* @ORM\ManyToMany(targetEntity="Term", inversedBy="pages")
*/
protected $terms;
public function __construct()
{
$this->terms = new ArrayCollection();
}
/**
* @return mixed
*/
public function getTerms()
{
return $this->terms;
}
/**
* @param mixed $terms
*/
public function setTerms($terms)
{
$this->terms = $terms;
}
}
/**
* @ORM\Entity(repositoryClass="AppBundle\Repository\TermRepository")
* @ExclusionPolicy("all")
*/
class Term
{
/**
* @ORM\ManyToMany(targetEntity="Page", mappedBy="terms", cascade={"persist"}, fetch="LAZY"))
*/
protected $pages;
public function __construct()
{
$this->pages = new ArrayCollection();
}
public function getPages()
{
return $this->pages;
}
public function setPages($pages)
{
$this->pages = $pages;
}
}
$ignoreTerms
数组
$ignoreTerms = [
$this->getParameter('param1'),
$this->getParameter('param2'),
$this->getParameter('param3'),
$this->getParameter('param4'),
];
页面存储库
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('p')
->from('AppBundle:Page', 'p')
->leftJoin('p.terms','tt'); // probably wrong use of join here
if(!empty($limit))
$qb->setMaxResults($limit);
if (!empty($ignoreTerms)) {
$qb->andWhere(
$qb->expr()->notIn('tt.id', $ignoreTerms)
);
}
return $qb;
查询生成器生成的 SQL(删除问题中不需要的其他条件后)
SELECT p0_.*
FROM page p0_ LEFT JOIN page_term p2_ ON p0_.id = p2_.page_id
LEFT JOIN term t1_ ON t1_.id = p2_.term_id
WHERE t1_.id NOT IN (--the array here--)
ORDER BY p0_.`publishDate`
DESC LIMIT 15 OFFSET 0
运行查询生成器时,它会忽略包含数组中的术语的页面。但是,没有术语的页面也会被忽略。
我期望它做的是获取带有或不带有术语的页面
可用的加入方法有
join()
innerJoin()
leftJoin()
都试过了,还是没有变化
要获取除忽略条款之外的所有页面,需要使用
OR
。
最终查询
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('p')
->from('AppBundle:Page', 'p')
->leftJoin('p.terms','tt'); // probably wrong use of join here
->where($qb->expr()->orX(
$qb->expr()->isNull('tt.id'), // Include pages with no terms
$qb->expr()->notIn('tt.id', ':ignoreTerms') // Exclude specific terms
))
->setParameter('ignoreTerms', $ignoreTerms);
if(!empty($limit))
$qb->setMaxResults($limit);
return $qb;