Пользовательский QueryBuilder в Doctrine - PullRequest
0 голосов
/ 22 января 2019

У меня есть эта проблема, я хотел бы создать «умные» критерии. Предположим, есть модель 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 голосов
/ 22 января 2019

Вы можете расширить 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');
    }
}
В вашем репозитории перезаписать метод createQueryBuilder:
class BookRepository extends EntityRepository
{
    public function createQueryBuilder($alias, $indexBy = null)
    {
        return (new BookQueryBuilder($this->_em))
            ->select($alias)
            ->from($this->_entityName, $alias, $indexBy);
    }
}
Используйте новый метод
$qb = $em->getRepository('Books')->createQueryBuilder('b')
    ->whereAuthorIsAlive();
0 голосов
/ 22 января 2019

Я использовал такой же тип в хранилище.

Я создал методы в классе репозитория, которые добавили части 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');
...