Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

CliffordAtCaveoDotNL's avatar

Livewire and Spatie's Query Builder

If anyone is struggling with Livewire and Spatie's Query Builder, here's a quick tip on how to get it working with filters:

Component:

<?php

namespace App\Http\Livewire;

use App\Item;
use Livewire\Component;
use Spatie\QueryBuilder\QueryBuilderRequest;

class Table extends Component
{
    /** @var QueryBuilderRequest */
    protected $request;

    /** @var array<string,string> */
    public $filter = [];

    /** @var array<string> */
    protected $updatesQueryString = [
        'filter',
    ];

    public function mount(): void
    {
        $this->filter = $this->request()->query('filter', $this->filter);
    }

    public function request(): QueryBuilderRequest
    {
        if (!$this->request) {
            $this->request = app(QueryBuilderRequest::class);
        }

        return $this->request;
    }

    public function filter(string $filter, ?string $slug): void
    {
        if (is_null($slug)) {
            unset($this->filter[$filter]);
        } else {
            $this->filter[$filter] = $slug;
        }

        $this->request()->query->set('filter', $this->filter);
    }

    public function render(): View
    {
        $items = QueryBuilder::for(Item::query(), $this->request())
            ->allowedFilters(Item::allowedFilters())
            ->get();

        return view('livewire.table', compact('items'));
    }
}

View:

<a role="button" href="#" wire:click.prevent="filter('filter-name', 'filter-value')">Filter!</a>
<a role="button" href="#" wire:click.prevent="filter('filter-name')">Reset!</a>

Hope this helps!

0 likes
5 replies
saddev's avatar

This doesnt work anymore. Anyone have a solution to this anno 2022?

authanram's avatar

That's how I do it, in 2023 with Livewire 3 and spatie/laravel-query-builder 5.6.0:

<?php

namespace App\Http\Livewire;

use App\Models\User;
use Illuminate\Http\Request;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
use Spatie\QueryBuilder\QueryBuilder;

class Table extends Component
{
	use WithPagination;

    #[Url]
    public string $sort = '';

    public function render(): View
    {
        $request = request();
        $request->query->set('sort', $this->sort);

        $paginator = self::queryBuilder($request)
            ->paginate()
            ->appends($request->query());

        return view('table', compact('paginator'));
    }

    private static function queryBuilder(Request $request): QueryBuilder
    {
        return QueryBuilder::for(User::class, $request)
            ->allowedSorts(['name', 'email']);
    }
}

Hope it helps.

1 like

Please or to participate in this conversation.