Правильный способ использования класса пагинации в Symfony

Я пытаюсь использовать этот пакет Symfony: https://github.com/KnpLabs/KnpPaginatorBundle

В документах они используют его как контроллер. Таким образом, у них есть легкий доступ к сервисному контейнеру или объекту запроса.

Но насколько я понимаю, запрос Doctrine должен быть в репозитории, а не в контроллере, верно? И у меня уже есть функция, возвращающая записи. Просто служба разбивки на страницы не ожидает «результатов» при создании экземпляра. Он хочет запрос. Поэтому я не могу вернуть «результаты» контроллеру, а в середине этой функции использую пагинатор.

С другой стороны, такие вещи, как игра с сервисами или запросами, действительно принадлежат контроллерам.

Итак, как это должно быть сделано? Сначала я думал внедрить сервис "knp_paginator" и объект запроса в репозиторий. Но я не думаю, что это правильный путь.


person konrad_firm    schedule 21.03.2016    source источник


Ответы (3)


Я бы сказал, что объект запроса не должен идти дальше по стеку, чем от контроллера.

Ничто не мешает вам внедрить пагинатор прямо в ваш пользовательский репозиторий, так почему бы не сделать это?

your.repository.service.definition:
    class: Your\Repository\Class

    # for symfony 2.3
    factory_service: doctrine
    factory_method: getRepository

    # for symfony 2.8 and higher
    factory: ["@doctrine.orm.entity_manager", getRepository]

    arguments:
      - YourBundle:YourEntity
    calls:
        - [setPaginator, ["@knp_paginator"]]

В репозитории у вас должен быть доступ к пагинатору для использования с QueryBuilder:

public function setPaginator($paginator)
{
    $this->paginator = $paginator;
}

...

$this->paginator->paginate($qb->getQuery(), $page, $limit);

Чтобы получить ваши переменные $page и $limit в репозиторий, вам не нужен объект Request. Просто передайте их в качестве параметра вызову репозитория:

// In your controller
// You can use forms here if you want, but for brevity:
$criteria = $request->get('criteria');
$page = $request->get('page');
$limit = $request->get('limit');

$paginatedResults = $myCustomRepository->fetchPaginatedData($criteria, $page, $limit);

Передача объекта запроса дальше по контроллеру означает, что у вас есть утечка в ваших абстракциях. Ваше приложение не должно знать об объекте Request. На самом деле запрос вполне может исходить из других источников, таких как команда CLI. Вы не хотите создавать объект Request из-за неправильного уровня абстракции.

person hasumedic    schedule 21.03.2016
comment
Но мне нужен объект Request для получения параметров URL ( $request-›query-›getInt('page', 1) ), но я также подумал, что мы не должны никуда передавать этот объект... - person konrad_firm; 21.03.2016

Предполагая, что у вас есть класс пользовательского репозитория, вы можете есть метод в этом репозитории, который возвращает запрос или действительный экземпляр построителя запросов, а затем вы вызываете этот метод из контроллера и передаете его методу paginate().

person Vamsi Krishna B    schedule 21.03.2016

Например, когда $qb возвращается пользовательским репозиторием (не возвращает результат, а только его построитель запросов)

$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
    $qb->getQuery(),
    $request->query->getInt($pageParameterName, 1),
    $perPage,
    array('pageParameterName' => $pageParameterName)
);
person darkomen    schedule 21.03.2016