php 52 lines · 7 steps

Adding RFC 5988 Link headers in Laravel

A helper class turns a Laravel paginator into standard Link and X-* pagination headers on a JSON response.

Explained by highlit
1<?php
2 
3namespace App\Http\Support;
4 
5use Illuminate\Contracts\Pagination\LengthAwarePaginator;
6use Illuminate\Http\JsonResponse;
7 
8class PaginationLinkHeader
9{
10 public function attach(JsonResponse $response, LengthAwarePaginator $paginator): JsonResponse
11 {
12 $links = $this->buildLinks($paginator);
13 
14 if ($links !== []) {
15 $response->headers->set('Link', implode(', ', $links));
16 }
17 
18 $response->headers->set('X-Total-Count', (string) $paginator->total());
19 $response->headers->set('X-Page', (string) $paginator->currentPage());
20 $response->headers->set('X-Per-Page', (string) $paginator->perPage());
21 $response->headers->set('X-Total-Pages', (string) $paginator->lastPage());
22 
23 return $response;
24 }
25 
26 private function buildLinks(LengthAwarePaginator $paginator): array
27 {
28 $relations = array_filter([
29 'first' => $paginator->url(1),
30 'prev' => $paginator->previousPageUrl(),
31 'next' => $paginator->nextPageUrl(),
32 'last' => $paginator->url($paginator->lastPage()),
33 ]);
34 
35 $links = [];
36 
37 foreach ($relations as $rel => $url) {
38 $links[] = sprintf('<%s>; rel="%s"', $this->withPageQuery($url, $paginator), $rel);
39 }
40 
41 return $links;
42 }
43 
44 private function withPageQuery(string $url, LengthAwarePaginator $paginator): string
45 {
46 $separator = str_contains($url, '?') ? '&' : '?';
47 
48 return $url . $separator . http_build_query([
49 'per_page' => $paginator->perPage(),
50 ]);
51 }
52}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1The RFC 5988 Link header lets API clients navigate pagination without parsing your response body.
  2. 2Filtering out null URLs keeps first/prev/next/last relations honest at the edges of a result set.
  3. 3Preserving query parameters when rewriting URLs avoids silently dropping the client's page size.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Adding RFC 5988 Link headers in Laravel — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code