• Как сделать ЧПУ пагинацию на Yii2?

    mulat
    @mulat
    seo, php, yii2
    Как раз только что с этим разобрался. Приведу пример кода из своего проекта.
    Вариант для yii\widgets\ListView
    Контроллер:
    $dataProvider = new ActiveDataProvider([
                'query' => Post::find()->andWhere(['category_id' => $model->id]),
                'pagination' => [
                    // Размер выводимых элементов на страницу. 
                    // Беру из настроек своего модуля blog
                    'pageSize' => Yii::$app->getModule('blog')->postPerPage,
                    // Размер эл-тов на страницу по умолчанию. Зачем нужен - поясню после кода
                    'defaultPageSize' => Yii::$app->getModule('blog')->postPerPage,
                    // Имя параметра, содержащего номер текущей страницы. 
                    // (если Ваш отличается от дефолтного 'page')
                    'pageParam' => 'pageNum',
                    // Так подавляется ссылка на первую страницу вида /category-name-х/1/
                    // Вместо неё выведется  /category-name-х/
                    'forcePageParam' => false,
                ]
            ]);


    Значение 'defaultPageSize' нужно установить равным значению 'pageSize' для того, чтобы подавить добавление классом Pagination параметра 'per-page' в урлы постранички. Но это нужно для того случая, когда не устраивает значение родного 'pageSize'. По-моему равно 20-ти.


    Так же требуется url первой страницы менять с такого mysite.ru/controllerName?page=1&per-page=2 на такой mysite.ru/controllerName

    Этот момент решается установкой параметра 'forcePageParam' в значение false.

    Для того, чтобы подхватывался route из Вашего urlManager, нужно чтобы описанный в менеджере pattern содержал правильные имена параметров. Т.е. в настройках класса Pagination - значение 'pageParam' по умолчанию задано как 'page'. Значит pattern для урлов должен быть такого плана:
    //...
    // Category with pager
     [
        'pattern' => '<alias:[\w\-]+>/<page:\d+>',
        'route' => 'blog/category/index',
        'suffix' => '/'
      ],
    //...


    В моём случае pattern для урлов такой:
    'pattern' => '<alias:[\w\-]+>/<pageNum:\d+>'

    P.S.
    В итоге мне самому этот вариант не подошёл, т.к. я хотел в постраничке оставить только ссылки на сами страницы без ссылок Следющий и Предыдщий пост. Не нашёл как сделать под ListView. А в LinkPager без проблем.
    Вариант для yii\widgets\LinkPager
    Контроллер:
    $query = Post::find()->andWhere(['category_id' => $model->id]);
            $countQuery = clone $query;
            $pages = new Pagination([
                'totalCount' => $countQuery->count(),
                'pageSize' => Yii::$app->getModule('blog')->postPerPage,
                'defaultPageSize' => Yii::$app->getModule('blog')->postPerPage,
                'pageParam' => 'pageNum',
                'forcePageParam' => false,
            ]);
            $postModels = $query->offset($pages->offset)->limit($pages->limit)->all();
    
            return $this->render('index', [
                'postModels' => $postModels,
                'pages' => $pages,
            ]);


    Представление:
    echo LinkPager::widget([
                'pagination' => $pages,
                // Отключаю ссылку "Следующий"
                'nextPageLabel' => false,
                // Отключаю ссылку "Предыдущий"
                'prevPageLabel' => false,
            ]);


    Вроде на оба вопроса ответил.

    P.S.

    Использую доработанный LinkPager. В частности ради настройки `activeLinkable` (не ссылаться на активную страницу), отображения номера конечной страницы и вывода островной нумерации:
    1,2,3,4 ... 44 [45] 46 ... 999
    Ответ написан
    1 комментарий