为了创建一个基于多个条件返回实体的组合查询,链接自定义存储库方法的正确方法是什么。
这是我做的:
use Doctrine\ORM\EntityRepository;
class ingredientRepository extends EntityRepository
{
private $query;
public function initNewQuery()
{
$this->query = $this->createQueryBuilder('i')->join('i.product', 'p');
return $this;
}
public function clearQuery()
{
$this->query = null;
return $this;
}
public function getResult(){
$r = $this->query->getQuery()->getResult();
$this->clearQuery();
return $r;
}
public function filterByProductName( $productName )
{
if(!$this->query) $this->initNewQuery();
$this->query->andWhere('p.name LIKE :name')->setParameter('name', '%'.$productName.'%');
return $this;
}
public function filterByMinContenu( $contenu )
{
if(!$this->query) $this->initNewQuery();
$this->query->andWhere('p.contenu > :contenu')->setParameter('contenu', $contenu);
return $this;
}
public function filterByType( $type ){
if(!$this->query) $this->initNewQuery();
$this->query->andWhere('i.type = :type')->setParameter('type', $type);
return $this;
}
}
这允许我做以下事情:
$ingredients = $em->getRepository('ingredient')->initNewQuery()->filterByType(4)->getResult();
$ingredients = $em->getRepository('ingredient')->initNewQuery()->filterByProductName('ell')->filterByMinContenu(10)->getResult();
这正是我想要的!
但是......我不是很喜欢它。
首先,这不是像findBy
等默认方法的工作原理。这些都直接返回结果。因此,混合这两种行为似乎并不合适。
其次,当只调用filterByType
方法然后返回结果时,查询将使用它不需要的连接。我想只有在需要的时候我才能找到一种方法来进行连接,但是再次,似乎没有。
关于如何做到这一点的任何想法清理简单?
答案 0 :(得分:0)
快速回答而不进行测试:)
use Doctrine\ORM\EntityRepository;
class ingredientRepository extends EntityRepository
{
private $query;
private function initNewQuery()
{
$this->query = $this->createQueryBuilder('i');
}
public function findBy($filterArray)
{
$this->initNewQuery();
if (array_key_exists('productName', $filterArray)) {
$this->filterByProductName($filterArray['productName']);
}
if (array_key_exists('minContenu', $filterArray)) {
$this->filterByMinContenu($filterArray['minContenu']);
}
if (array_key_exists('type', $filterArray)) {
$this->filterByType($filterArray['type']);
}
return $this->query->getQuery()->getResult();
}
private function filterByProductName($productName)
{
$this->query->join('i.product', 'p');
$this->query->andWhere('p.name LIKE :name')->setParameter('name', '%'.$productName.'%');
}
private function filterByMinContenu($contenu)
{
$this->query->andWhere('p.contenu > :contenu')->setParameter('contenu', $contenu);
}
private function filterByType($type)
{
$this->query->andWhere('i.type = :type')->setParameter('type', $type);
}
}
呼叫:
$ingredients = $em->getRepository('ingredient')->findBy(['type'=>4]);
$ingredients = $em->getRepository('ingredient')->findBy(['productName'=>'ell', 'minContenu' => 10]);