spatie/laravel-query-builder

repository·main·Indexed 26 days ago

https://github.com/spatie/laravel-query-builder

A tool for building Eloquent queries directly from API requests. It allows developers to implement filtering (including partial, exact, operator, scope, and callback filters), sorting, including relationships, and field selection. The package extends Laravel's default Eloquent query builder, enabling integration with existing queries and standard Laravel methods like paginate().

Tokens
16.6K
Snippets
70
Records
88
Agent score
82%

What's inside spatie/laravel-query-builder

  1. Basic Usage of Laravel Query Builder

    main

    Use QueryBuilder::for() to wrap an Eloquent model or query. You must explicitly define which filters, sorts, includes, and fields are allowed to prevent unauthorized query parameters from being processed. Unallowed parameters will throw exceptions by default.

    use Spatie\QueryBuilder\QueryBuilder;
    use Spatie\QueryBuilder\AllowedFilter;
    use Spatie\QueryBuilder\AllowedInclude;
    use Spatie\QueryBuilder\AllowedSort;
    
    // GET /users?filter[name]=John&sort=-created_at&include=posts
    $users = QueryBuilder::for(User::class)
        ->allowedFilters('name', 'email')
        ->allowedSorts('name', 'created_at')
        ->allowedIncludes('posts', 'permissions')
        ->allowedFields('id', 'name', 'email')
        ->get();
  2. Use a custom base query with QueryBuilder

    main

    Instead of passing a Model's Fully Qualified Class Name (FQCN) to QueryBuilder::for(), you can pass an existing Eloquent query builder instance. This allows you to start with a pre-filtered or specific query and then apply laravel-query-builder features like allowedIncludes on top of it.

    QueryBuilder::for(User::where('id', 42)) // base query instead of model
        ->allowedIncludes('posts')
        ->where('activated', true) // chain on any of Laravel's query methods
        ->first(); // we only need one specific user
  3. Check system requirements for Laravel Query Builder

    main

    To use the latest version of the Laravel Query Builder package, ensure your environment meets the following minimum requirements:

    • PHP: 8.3 or above
    • Laravel: 12 or above

    If your environment does not meet these requirements, you must use an older version of the package compatible with your current setup.

  4. Filter queries using QueryBuilder

    main

    You can filter Eloquent models based on request parameters (e.g., /users?filter[name]=John) by specifying which fields are allowed to be filtered using the allowedFilters() method. This follows the JSON API specification for query parameters.

    use Spatie\QueryBuilder\QueryBuilder;
    
    $users = QueryBuilder::for(User::class)
        ->allowedFilters('name')
        ->get();
    
    // all `User`s that contain the string "John" in their name
  5. Select specific fields using allowedFields()

    main

    To reduce SQL query size, you can restrict the columns returned by a query using the allowedFields() method combined with the fields request query parameter.

    When using this feature, the fields query parameter follows the format fields[MODEL_NAME]=field1,field2.

    Important: The fields query parameter will completely override the SELECT part of the SQL query. If you are using Eloquent relationships, you must manually include any columns required for those relationships to function (e.g., the foreign keys or the primary keys of the related models).

    // GET /users?fields[users]=id,name
    
    $users = QueryBuilder::for(User::class)
        ->allowedFields('id', 'name')
        ->get();
  6. Select fields for included relations

    main

    You can limit the columns returned for included relationships by using dot notation in allowedFields().

    Naming Convention: In allowedFields(), you must use the snake_case plural version of your relation name (e.g., if the relation is author, use authors.id). This behavior can be modified in the package configuration file.

    Example: To include an author but only fetch their id and name:

    GET /posts?include=author&fields[authors]=id,name

    // GET /posts?include=author&fields[authors]=id,name
    
    QueryBuilder::for(Post::class)
        ->allowedFields('authors.id', 'authors.name')
        ->allowedIncludes('author')
        ->get();
  7. Upgrade from v1 to v2

    main

    Upgrading from v1 to v2 involves significant renaming and architectural changes:

    • Rename Sort to AllowedSort.
    • Rename Included to AllowedInclude.
    • Rename Filter to AllowedFilter.
    • Replace request macros (e.g., request()->filters()) with QueryBuilderRequest::fromRequest($request)->filters().
    • AllowedSort::custom() and AllowedFilter::custom() now require an instance of the class, not the class name.
    • allowedFields() must be called before allowedIncludes().
    // Before
    AllowedSort::custom('name', MySort::class)
    AllowedFilter::custom('name', MyFilter::class)
    
    // After
    AllowedSort::custom('name', new MySort())
    AllowedFilter::custom('name', new MyFilter())
  8. Upgrade from v2 to v3

    main
    In v3, Spatie\QueryBuilder\QueryBuilder no longer extends Laravel's Illuminate\Database\Eloquent\Builder. While all Eloquent methods are still forwarded, you can no longer pass a QueryBuilder instance to methods expecting an Eloquent Builder. Use $queryBuilder->getEloquentBuilder() to access the underlying Eloquent builder.