Table of Contents
When you’re building a search API with Laravel Scout and want to follow the JSON:API specification for pagination, you might run into a compatibility problem: packages like spatie/laravel-json-api-paginate don’t work with Scout queries, and packages that do support Scout (like jackardios/scout-json-api-paginate) might not support your Laravel version.
The good news? You can add this functionality yourself with a simple Scout macro.
The Problem
JSON:API uses a specific pagination format:
GET /api/reports?q=sales&page[number]=2&page[size]=20
But Scout’s built-in paginate() method expects Laravel’s standard pagination parameters. You need a bridge between these two formats.
The Solution
Add a macro to Scout’s Builder class in your AppServiceProvider:
// app/Providers/AppServiceProvider.php
use Laravel\Scout\Builder as ScoutBuilder;
public function boot()
{
ScoutBuilder::macro('jsonPaginate', function ($maxResults = null, $defaultSize = null) {
$maxResults = $maxResults ?? 30;
$defaultSize = $defaultSize ?? 15;
$numberParam = config('json-api-paginate.number_parameter', 'page[number]');
$sizeParam = config('json-api-paginate.size_parameter', 'page[size]');
$size = (int) request()->input($sizeParam, $defaultSize);
$size = min($size, $maxResults);
$number = (int) request()->input($numberParam, 1);
return $this->paginate($size, 'page', $number);
});
How to Use It
Now you can use jsonPaginate() on any Scout search query:
// In your controller
public function search(Request $request)
{
$query = $request->input('q');
$results = Report::search($query)
->query(fn ($builder) => $builder->where('active', true))
->jsonPaginate();
return $results;
}
Your API will now accept JSON:API pagination parameters:
GET /api/reports?q=sales&page[number]=2&page[size]=20
Why This Works
The macro:
- Reads the JSON:API-style
page[number]andpage[size]parameters - Enforces a max results limit (prevents clients from requesting too many results)
- Converts these to Scout’s expected format:
paginate($perPage, $pageName, $page) - Returns a standard Laravel paginator that works with Scout
You get JSON:API-compliant pagination without adding a whole package or creating a custom service provider.
Configuration
If you’re using spatie/laravel-json-api-paginate for your Eloquent queries, this macro will automatically use the same configuration keys from config/json-api-paginate.php. If not, it defaults to page[number] and page[size].
Tip: This pattern works for any Laravel class you want to extend. Macros are a lightweight way to add functionality without modifying vendor code or creating inheritance hierarchies.
Leave a Reply