Doctrine中的自定义QueryBuilder

时间:2019-01-22 12:02:54

标签: php doctrine-orm

我有这个问题,我想创建“智能”标准。假设有一个作者为1的模型:n本书。

所以,而不是:

$qb = $em->getRepository('Books')->createQueryBuilder('b')
    ->join('b.author', 'a')
    ->where('a.dod is null')
    ->where('a.name = :name')
    ->setParameter('name', 'Mozart');
    ;

...我想做类似的事情:

$qb = $em->getRepository('Books')->createQueryBuilder('b')
    ->whereAuthorIsAlive()
    ->whereAuthorName('Mozart');

我知道创建自定义EntityManager的可能性,但事实并非如此。自定义QueryBuider会更合适。

2 个答案:

答案 0 :(得分:2)

您可以使用自定义方法来扩展QueryBuilder,但是通过覆盖存储库的createQueryBuilder方法可以节省一些开销:

  1. 扩展默认的QueryBuilder类:
class BookQueryBuilder extends \Doctrine\ORM\QueryBuilder 
{
    public function whereAuthorIsAlive(): self 
    {
        return $this->join($this->getRootAlias() . '.author', '_a')
            ->andWhere('_a.alive = true');
    }
}
  1. 在您的存储库中,覆盖createQueryBuilder方法:
class BookRepository extends EntityRepository
{
    public function createQueryBuilder($alias, $indexBy = null)
    {
        return (new BookQueryBuilder($this->_em))
            ->select($alias)
            ->from($this->_entityName, $alias, $indexBy);
    }
}
  1. 使用新方法
$qb = $em->getRepository('Books')->createQueryBuilder('b')
    ->whereAuthorIsAlive();

答案 1 :(得分:1)

我在存储库中使用过这种类型的东西。

我在存储库类中创建了将QueryBuilder部件添加到查询中的方法。

例如,基于您的:

namespace App\Repository;

class BooksRepository extends EntityRepository
{
    private function whereAuthorIsAlive($qb)
    {
        $qb->where('a.dod is null');
        return $qb;
    }

    private function whereAuthorName($qb, $name)
    {
        $qb->where('a.name = :name')
           ->setParameter('name', $name);

        return $qb;
    }

    public function getBooksByAliveAuthorName($name)
    {
        $qb = $this->createQueryBuilder('b')
                   ->join('b.author', 'a')

        $qb = $this->whereAuthorIsAlive($qb);
        $qb = $this->whereAuthorName($qb, $name);

        return $qb->getQuery()->getResult();
    }
}

要向您的实体注册此存储库:

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\BooksRepository")
 */
class Books
{
    // your entity
}

然后,在控制器中:

$books = $this->getDoctrine()
              ->getRepository('App:Books')
              ->getBooksByAliveAuthorName('Mozart');