Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Middle: питання на співбесіді з теми «Пагінація»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

2 питання

Класична скарга: користувач вибрав фільтри, перейшов на другу сторінку - і фільтри злетіли. Причина в тому, що посилання пагінації за замовчуванням несуть лише page.

Додати поточні параметри:

$posts = Post::filter($request)->paginate(15)->withQueryString();

withQueryString() переносить усі параметри рядка запиту в посилання пагінації. Якщо потрібні конкретні - appends():

$posts->appends(['sort' => $request->input('sort')]);

Друга частина проблеми - сортування без унікального ключа. Якщо сортувати за колонкою з повторами, рядки з однаковим значенням база може віддати в різному порядку на різних сторінках - і один запис зʼявиться двічі, а інший зникне:

// хитко: багато записів з однаковою датою
Post::orderByDesc('published_at')->paginate(15);

// стабільно: дозволяємо ключем
Post::orderByDesc('published_at')->orderByDesc('id')->paginate(15);

Третя - сторінка поза межами. Після зміни фільтра запис може стати менше, ніж потрібно для сторінки 7, і користувач бачить порожньо. Скидання номера сторінки при зміні фільтра вирішує це; у Livewire для того є resetPage().

Для SEO варто памʼятати ще про одне: кожна комбінація фільтрів із номером сторінки - окрема URL. Якщо їх багато, сторінки з фільтрами зазвичай закривають від індексації, лишаючи в ній базовий список.

Докладніше в документації: Пагінація

Скільки номерів показувати навколо поточної сторінки:

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

За замовчуванням - по три з кожного боку. На мобільних onEachSide(1) робить навігацію компактною.

Вбудовані шаблони: за замовчуванням Laravel генерує розмітку для Tailwind CSS. Для Bootstrap - один раз у провайдері:

// AppServiceProvider::boot()
Paginator::useBootstrapFive();

Власний шаблон для всього застосунку:

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

Шаблони копіюються в resources/views/vendor/pagination, і їх можна змінювати. Або вказати свої за замовчуванням:

Paginator::defaultView('pagination.compact');
Paginator::defaultSimpleView('pagination.simple-compact');

Окремий шаблон для конкретного місця:

{{ $users->links('pagination.admin') }}

Параметри в посиланнях:

$users = User::paginate(20)->withQueryString();          // зберегти поточні фільтри
$users = User::paginate(20)->appends(['sort' => 'name']); // додати свої параметри
$users = User::paginate(20)->fragment('users');           // #users наприкінці посилань
$users = User::paginate(20)->withPath('/admin/users');    // інший базовий шлях

fragment корисний, коли список - не на початку сторінки: після переходу браузер прокручує до потрібного блоку.

Кілька пагінаторів на одній сторінці - різні назви параметра, інакше обидва реагують на ?page=:

$posts = Post::paginate(10, pageName: 'posts');
$comments = Comment::paginate(10, pageName: 'comments');

Доступні дані в шаблоні: $paginator->currentPage(), lastPage(), total(), firstItem(), lastItem(), hasMorePages(), previousPageUrl(), nextPageUrl() - з них можна зібрати навігацію будь-якого вигляду.

SEO й доступність у власному шаблоні: справжні посилання <a href> (а не кнопки з JavaScript), rel="prev"/rel="next", aria-current="page" для поточної сторінки, aria-label для стрілок.

Докладніше в документації: Налаштування вигляду пагінації