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






Я использовал такой же в репозитории.
Я создал методы в классе репозитория, которые добавляли в запрос части 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');
Вы можете расширить QueryBuilder с помощью своих пользовательских методов, но иметь небольшие накладные расходы, перезаписав метод createQueryBuilder вашего репозитория:
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();
Спасибо, это именно то, что мне нужно. Только я думаю, что createQueryBuilder должен быть: return (new BookQuery($this->_em))->select($alias)->from($this->_entityName, $alias, $indexBy); (согласно \Doctrine\ORM\EntityManager::createQueryBuilder)
печально ocramius написал: "Теоретически QueryBuilder должен быть окончательным" github.com/doctrine/orm/issues/7868#issuecomment-542225533 "Помещение DQL непосредственно в строку NOWDOC гораздо более читабельно" reddit.com/r/PHP/comments/a58yt9/…
Я бы поспорил с NOWDOC. Возьмите мой пример выше (whereAuthorIsAlive, который имеет 1 соединение и 1 критерий), теперь документ не будет более читабельным. И я не понимаю, почему желание сделать QueryBuilder окончательным? Я думаю, что мои пожелания по пользовательским критериям совершенно законны :)
Проблема в том, что у меня больше двух критериев, тогда я должен написать комбинацию для всех из них...? Вот почему не хотел использовать реестр, поэтому предыдущий ответ лучше.