I got a chance to develop an internal dashboard with Inertia.js at my work and it’s an absolute joy to work with. For the uninitiated, Inertia.js helps to reduce some boilerplate you’ll need to have to make your server-side application behaves more like a single-page application. You can read more about how it works here.

To further reduce the work needed to fetch models from the database, I decided to use the excellent spatie/laravel-query-builder to fetch and prepare my Eloquent models for Inertia.js consumption. When pair with spatie/laravel-model-status, you can save a lot of time and will be able to focus on the business side of your application.

One issue that I have is the package doesn’t support sorting the model by its respective relationship. Luckily, it supports a custom sorting method by providing an invokable class that implements \Spatie\QueryBuilder\Sorts\Sort interface, so we can use it to our advantage. In my situation, I want to sort the resulting models fetched from the database by their status, so this is how the class looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace App\QueryBuilder;

use Spatie\ModelStatus\Status;
use Spatie\QueryBuilder\Sorts\Sort;
use Illuminate\Database\Eloquent\Builder;

class SortBySiteStatus implements Sort
{
    public function __invoke(Builder $query, bool $descending, string $property)
    {
        $direction = $descending ? 'DESC' : 'ASC';

        $query->orderBy(
            Status::select('name')
                ->whereColumn('statuses.model_id', 'sites.id')
                ->where('statuses.model_type', 'App\Models\Site'),
            $direction
        );
    }
}

Then, you will need to add that into the allowedSorts argument of your query builder.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

use App\Models\Site;
use Spatie\QueryBuilder\AllowedSort;
use Spatie\QueryBuilder\QueryBuilder;
use App\QueryBuilder\SortBySiteStatus;

...
    
QueryBuilder::for(Site::class)
    ->allowedSorts(
        AllowedSort::custom('status', new SortBySiteStatus),
    );

I’ve removed a bunch of unrelated codes for the above snippets, but you should get the idea. Thanks to this Github issue for nudging me in the right direction.