Стиль кода: Doctrine2 запрашивает из хранилища сущностей?

Как я понимаю, лучший стиль кода - это помещать сложные запросы SQL/DQL в репозитории сущностей.

Например, существует сущность с именем "Новости". Он имеет собственный репозиторий сущностей с именем "NewsRepository".

В контроллере есть этот код:

/**
 * @Route("/news", name="news")
 */
public function indexAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $paginator = $this->get('knp_paginator');

    $news = $paginator->paginate(
        $em->createQuery('SELECT n FROM AppBundle:News n'),
        $request->query->getInt('page', 1),
        10
    );

    return $this->render('app/news/list.html.twig', array(
        'news' => $news,
    ));
}

Теперь я люблю добавлять дополнительные функции (фильтрация, упорядочение по...). Это потому, что я думаю, что запрос должен быть перенесен в любой сервис или хранилище сущностей. Но как и каков лучший стиль кодирования?

(И есть ли у кого-нибудь хорошие общие идеи, как легко добавить фильтрацию, упорядочить по...?)

2 ответа

Решение

Конечно,

Каждый запрос должен быть в хранилище, если вы хотите использовать его снова. Не только самое сложное.

Я постараюсь ответить на ваш первый вопрос, а затем дам вам совет, который может помочь вам с вашей "общей фильтрацией"

Если вы хотите разместить свой запрос в репо, просто сделайте это в своем репозитории новостей:

public function findAllOrderedByDate() {
    $qb = $this->createQueryBuilder('n');
    $qb->orderBy('creationDate');

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

И в вашем контроллере:

public function indexAction(Request $request)
{
    $newsRepo = $this->get('doctrine')->getRepository('AppBundle:News');
    $em = $this->getDoctrine()->getManager();
    $paginator = $this->get('knp_paginator');

    $news = $newsRepo->findAllOrderedByDate();
    $pagination = $paginator->paginate(
        $news,
        $request->query->getInt('page', 1),
        10
    );

    return $this->render('app/news/list.html.twig', array(
        'news' => $pagination,
    ));
}

Для фильтрации у вас есть трюк в отчете, который состоит в возврате qb, а не в результате.

Также вы можете сделать функцию, которая добавит вам orderBy с заданным параметром (используя addOrderBy() или же andWhere) и которые возвращают queryBuilder. После всего этого вы можете обработать.

РЕДАКТИРОВАТЬ:


Решение, которое я прочитал в этой теме:

public function findAllOrderedByDate(callable $func = null) {
    $qb = $this->createQueryBuilder('n');
    $qb->orderBy('creationDate');

    if (is_callable($func)) {
        return $func($qb);
    }
    return $qb->getQuery()->getResult();
}

и в вашем контроллере:

$func = function (QueryBuilder $qb) use ($paginator, $request) {
    return $paginator->paginate($qb, $request->query->getInt('page', 1), 10);
};
$pagination = $em->getRepository('AppBundle:News')->findAllOrderedByDate($func);

Модельная часть должна быть в модельной части. Переместить запросы в репо. И что вы имеете в виду, говоря это: "хорошие общие идеи, как легко добавить фильтрацию, упорядочить по"?
Сортировать по
Где - та же ссылка

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