Пагинация

Содержание:


Введение

Работа с постраничным разбиением запросов (пагниацией) в других фреймворках может быть очень проблематичной. Пагинатор Laravel интегрирован с конструктором запросов и Eloquent ORM и предоставляет легкий для исопльзования способ пагинации результатов выборки из базы данных. Сгенерированный пагинатором HTML совместим с CSS фреймворком Bootstrap.


Типовое использование

Пагинация результатов конструктора запросов

Есть несколько способов провести пагинацию элементов выборки. Самый просто путь — это использовать метод paginate на конструктор запросов или Eloquent ORM. Метод paginate автоматически позаботится об установке необходимых лимитов и отступов основываясь на текущей странице просмотра пользователя. По умолчанию, текущая страница определяется по значению аргумента page для HTTP запроса. Это значение Ларавел определяет автоматически, также автоматически вставляет в ссылки на страницы генерируемые пагинатором.

В этом примере, единственный аргумент передаваемы в метод paginate — это число элементов, которое вы хотели бы отображать "постранично". В этом случае, давайте укажем, что вы хотели бы отобразить 15 элементов на странице:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class UserController extends Controller
{
    /**
     * Show all of the users for the application.
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::table('users')->paginate(15);

        return view('user.index', ['users' => $users]);
    }
}
На текущий момент, операдции пагинации, которые используют выражение groupBy, не могут выполняться Ларавел эффективно. Если вам необходимо использовать groupBy с набором разбитых на страницы результатов, то рекомендуется провести запрос к базе данных и создать пагинатор вручную.

"Простая" пагинация

Если вам только лишь необходимо вывести простые ссылки "След." и "Пред." для вашего представления, вы можете использовать метод simplePaginate для реализации более эффективного запроса. Это очень практично для больших наборов данных не показывать ссылку на каждый номер, при отработке вашего представления:

$users = DB::table('users')->simplePaginate(15);

Пагинация результатов Eloquent

Вы также можете проводить пагинацию запросов Eloquent. В этом примере мы разобьём на страницы модель User по 15 элементов на странице. Как вы сможете увидеть, синтаксис очень похож на пагинацию конструктора запросов:

$users = App\User::paginate(15);

Вы можете также вызвать paginate после других ограничений для запроса, таких как условия where:

$users = User::where('votes', '>', 100)->paginate(15);

Вы можете также использовать метод simplePaginate для пагинации моделей Eloquent:

$users = User::where('votes', '>', 100)->simplePaginate(15);

Создание пагинации вручную

Иногда вы можете захотеть создать паганицию вручную, путём передачи массива элементов. Вы можете так поступить путём создания экземпляра Illuminate\Pagination\Paginator или Illuminate\Pagination\LengthAwarePaginator в зависимости от ваших нужд.

Класс Paginator может не располагать информацией об общем числе элементов в наборе результав. Как следствие, у класса нет методом для получения индекса последней страницы. Метод LengthAwarePaginator принимает практически те же аргументы, что и Paginator. Однако, отличительной чертой является то, что метод LengthAwarePaginator число элементов в выборке.

Другими словами, метод Paginator соответвует методу simplePaginate для конструктора запросов или Eloquent, в то время как LengthAwarePaginator соответсвует методу paginate.

При создании пагинатора вручную, вы должны вручную делать нарезку массива, который вы передаёте в пагинатор. Если у вас есть сомнения по поводу того, как это сделать, рекомендуется проверить информацию о функции PHP array_slice.

Отображение результатов пагинации

При вызове метода paginate, вы будете получать экземпляр Illuminate\Pagination\LengthAwarePaginator. При вызове метода simplePaginate, вы получите экземпляр Illuminate\Pagination\Paginator. Эти объекты предоставляют несколько методов, которые описывают набор результатов. Дополнительно к этим методам-помощникам, экзепляры пагинатора являются итераторами и их можно перебирать как массив. Поэтому, после получения результатов, вы можете отобразить результаты и сгенерировать ссылки страниц используя шаблонизатор Blade:

<div class="container">
    @foreach ($users as $user)
                    {{ $user->name }}
                @endforeach
</div>

{{ $users->links() }}

Метод links будет генерировать ссылки на остальные страницы в наборе результатов. Каждая из этих ссылок будет уже содержать необходимые переменные запроса page. Нужно запомнить, что HTML сгенерированный методом links подходит под разметку CSS фреймворка Bootstrap.

Настройка URI пагинатора.

Метод withPath позволяет вам настроить URI, используемый пагинатором при генерации ссылок. Например, есил вы хотите, чтобы пагинатор генерировал ссылки как http://example.com/custom/url?page=N, вам необходимо передать custom/url в метод withPath:

Route::get('users', function () {
    $users = App\User::paginate(15);

    $users->withPath('custom/url');

    //
});

Присоединение к ссылка пагинации

Вы можете добавить строку ссылок пагинации используя метод appends. Например, чтобы добавить sort=votes к каждой ссылке пагинации, вы должны сделать следующий вызов в appends:

{{ $users->appends(['sort' => 'votes'])->links() }}

Если вы хотите добавить "hash fragment" в URL пагинатора, вы можете использовать метод fragment. Например, для добавления #foo в конец каждой ссылки пагинации, сделайте следующий вызов в метод fragment:

{{ $users->fragment('foo')->links() }}

Настройка окна ссылок на страницы

Вы можете контролировать как много дополнительный ссылок показывается на каждой стороне URL "окна" пагинатора. По умолчанию, три ссылки показываются на каждой стороне от основных ссылок. Вы можете контролировать это число используя метод onEachSide:

{{ $users->onEachSide(5)->links() }}

Преобразование результатов в JSON

Преобразовать результаты выборки в JSON достаточно легко в силу того, что класс пагинатора Laravel расширяет интерфейс Illuminate\Contracts\Support\Jsonable и раскрывает метод toJson. Вы также можете преобразовать экземпляр пагинатора в JSON путём возвращения его из маршрута или действия контроллера:

Route::get('users', function () {
    return App\User::paginate();
});

JSON из пагинатора будет включать мета-информацию такую как: total, current_page, last_page и другую. Актуальные объекты-результаты будут доступны через ключ data в массиве JSON. Далее представлен пример создания JSON путём возвращения экземпляра пагинатора из маршрута:

{
   "total": 50,
   "per_page": 15,
   "current_page": 1,
   "last_page": 4,
   "first_page_url": "http://laravel.app?page=1",
   "last_page_url": "http://laravel.app?page=4",
   "next_page_url": "http://laravel.app?page=2",
   "prev_page_url": null,
   "path": "http://laravel.app",
   "from": 1,
   "to": 15,
   "data":[
        {
            // Result Object
        },
        {
            // Result Object
        }
   ]
}

Настройка внешнего вида пагинатора

По умолчанию, представления сгенерированное для отображение ссылок пагинации совместимо с CSS фреймворком Bootstrap. Однако, если вы не используете Bootstrap, вы можете легко определить ваши собственные представления для генерации этих ссылок. При вызове метода links на экзепляр пагинатора, передайте имя представления в качестве первого аргумента в метод:

{{ $paginator->links('view.name') }}

// Passing data to the view...
{{ $paginator->links('view.name', ['foo' => 'bar']) }}

Однако, самый простой способ настроить представления пагинации — экспортировать представления в вашу папку resources/views/vendor используя команду vendor:publish:

php artisan vendor:publish --tag=laravel-pagination

Эта команда поместит представления в папку resources/views/vendor/pagination. Файл bootstrap-4.blade.php внутри этой папки отвечает за базовое представление пагинации. Вы можете редактировать этот файл для изменения внешнего вида пагинации.

Если вы хотите разработать файл отличный от типового представления пагинации, вы можете использовать методы пагинатора defaultView и defaultSimpleView внутри вашего AppServiceProvider:

use Illuminate\Pagination\Paginator;

public function boot()
{
    Paginator::defaultView('view-name');

    Paginator::defaultSimpleView('view-name');
}

Методы пагинации

Каждый экземпляр пагинатора предоставляет дополнительную информацию с помощью следующих методов:

Метод Описание
$results->count() Получить число элементов для текущей страницы.
$results->currentPage() Получить текущий номер страницы.
$results->firstItem() Получить порядковый номер первого элемента из результатов.
$results->getOptions() Получить опции пагинатора.
$results->getUrlRange($start, $end) Создать диапазон URL-ов пагинации.
$results->hasMorePages() Определить, что есть достаточное число элементов для того, чтобы можно было разбить на несколько страниц.
$results->items() Получить элементы для текущей страницы.
$results->lastItem() Получить порядковый номер последнего элемента из результатов.
$results->lastPage() Получить номер последней возможной страницы (не доступно для simplePaginate).
$results->nextPageUrl() Получить URL для следующей страницы.
$results->onFirstPage() Определить, что пагинатор находится на первой странице.
$results->perPage() Число элементов для показа на каждой странице.
$results->previousPageUrl() Получить URL для предыдущей страницы.
$results->total() Определить общее число совпадающих элементов в хранилище данных. (Не доступно для simplePaginate).
$results->url($page) Получить URL для данного номера страницы.
$results->getPageName() Получить название страницы.
$results->setPageName($name) Установить название страницы.