Пользовательский QueryBuilder в Doctrine

У меня есть эта проблема, я хотел бы создать «умные» критерии. Предположим, есть модель 1 Author : n Books.

Итак, вместо:

$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 был бы более подходящим.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
1 829
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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

Проблема в том, что у меня больше двух критериев, тогда я должен написать комбинацию для всех из них...? Вот почему не хотел использовать реестр, поэтому предыдущий ответ лучше.

JohnSmith 22.01.2019 14:20
Ответ принят как подходящий

Вы можете расширить 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();

Спасибо, это именно то, что мне нужно. Только я думаю, что createQueryBuilder должен быть: return (new BookQuery($this->_em))->select($alias)->from($this->_entityN‌​ame, $alias, $indexBy); (согласно \Doctrine\ORM\EntityManager::createQueryBuilder)

JohnSmith 22.01.2019 14:18

печально ocramius написал: "Теоретически QueryBuilder должен быть окончательным" github.com/doctrine/orm/issues/7868#issuecomment-542225533 "Помещение DQL непосредственно в строку NOWDOC гораздо более читабельно" reddit.com/r/PHP/comments/a58yt9/…

c33s 15.10.2019 17:08

Я бы поспорил с NOWDOC. Возьмите мой пример выше (whereAuthorIsAlive, который имеет 1 соединение и 1 критерий), теперь документ не будет более читабельным. И я не понимаю, почему желание сделать QueryBuilder окончательным? Я думаю, что мои пожелания по пользовательским критериям совершенно законны :)

JohnSmith 26.10.2020 12:40

Другие вопросы по теме