В Laravel есть два способа разбивать данные на страницы: offset и cursor. Первый — старый дедовский способ, второй — более умный, но со своими нюансами. Разберём без воды, что и когда использовать.

Если у тебя в базе десятки миллионов строк, то слово paginate() может превратиться в слово из трёх букв. Потому что offset-пагинация на таких объёмах — это как тащить диван по лестнице: сначала идёт легко, потом уже хребет трещит.

Laravel даёт выбор: offset и cursor. Казалось бы, обе делают одно и то же — показывают страницы. Но разница принципиальная.

Offset пагинация

Классика жанра. Работает через LIMIT + OFFSET.

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

Laravel сам накрутит ссылки, выдаст links() и сделает красивую пагинацию. Всё просто.

Минусы:

  • Чем дальше страница, тем тяжелее запрос (OFFSET 1000000 — это боль).
  • Если данные изменяются (кто-то добавил/удалил строки), страницы начинают прыгать: на 2-й странице ты был, перешёл на 3-ю — и снова там.

Cursor пагинация

Более современный вариант. Работает через «указатель на последнюю запись».

$users = User::orderBy('id')->cursorPaginate(15);

Тут Laravel хранит «курсор» (например id последней строки) и на его основе достаёт следующие данные.

Плюсы:

  • Работает быстрее на больших данных (нет безумных OFFSET).
  • Нет дублей и пропусков, если таблица активно меняется.

Минусы:

  • Не всегда подходит, если надо прыгнуть «сразу на 100-ю страницу».

Что выбрать?

  • Offset — норм, если у тебя «новостная лента для 1000 записей» и нагрузка никакая. Просто работает и не паришься.
  • Cursor — нужен, если у тебя данные живые (например, лог событий, чат, транзакции) и таблица постоянно обновляется.

Вывод

  • Offset прост, но на больших таблицах превращается в ад.
  • Cursor умнее, но менее гибкий.

Хочешь стабильности и скорости — бери cursor. Хочешь привычности и «сразу на 100-ю страницу» — бери offset.