Урок 11

Пагинация и фильтры

Что такое пагинация

Пагинация — это разбивка большого списка на страницы. Если в таблице 10 000 постов, выводить их все сразу нельзя: это медленно и неудобно. Пагинация отдаёт только часть записей и ссылки для перехода между страницами.

Пагинация в Eloquent

$posts = Post::paginate(15);

Метод paginate возвращает объект LengthAwarePaginator, который содержит записи текущей страницы, общее количество, номер текущей страницы и ссылки.

Вывод в Blade:

@foreach ($posts as $post)
    <article>{{ $post->title }}</article>
@endforeach

{{ $posts->links() }}

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

$posts = Post::simplePaginate(15);

Не считает общее количество записей — только «Назад» и «Вперёд». Быстрее, если точное число не важно.

Курсорная пагинация

$posts = Post::orderBy('id')->cursorPaginate(15);

Для очень больших таблиц. Вместо OFFSET использует курсор, поэтому работает за константное время.

Фильтры

Фильтры — это условия, которые пользователь задаёт через query-параметры:

$query = Post::query();

if ($request->filled('search')) {
    $query->where('title', 'like', "%{$request->search}%");
}

if ($request->filled('status')) {
    $query->where('status', $request->status);
}

$posts = $query->paginate(15)->withQueryString();

withQueryString() сохраняет параметры фильтра в ссылках пагинации.

Безопасная сортировка

Нельзя передавать имя колонки напрямую из запроса. Нужен белый список:

$sort = $request->get('sort', 'created_at');
$direction = $request->get('direction', 'desc');

$allowed = ['title', 'created_at', 'views'];
if (!in_array($sort, $allowed)) {
    $sort = 'created_at';
}

$posts = Post::orderBy($sort, $direction)->paginate(15);

API-пагинация

return response()->json(Post::paginate(15));

Ответ содержит:

{
    "data": [...],
    "current_page": 1,
    "last_page": 5,
    "per_page": 15,
    "total": 73,
    "links": {...}
}