Skip to content

Основы использования ​

Spatie-совместимый API — это класс QueryBuilder. Он оборачивает Eloquent-запрос и применяет параметры запроса клиента, которые вы разрешили:

php
use App\Models\User;
use MyProgs\QueryBuilder\AllowedFilter;
use MyProgs\QueryBuilder\AllowedSort;
use MyProgs\QueryBuilder\QueryBuilder;

class UserController
{
    public function index()
    {
        return QueryBuilder::for(User::class)
            ->allowedFields('id', 'name', 'email', 'posts.id', 'posts.title')
            ->allowedIncludes('posts', 'posts.comments')
            ->allowedFilters('name', AllowedFilter::exact('id'), AllowedFilter::scope('active'))
            ->allowedSorts('name', AllowedSort::field('created', 'created_at'))
            ->defaultSort('-created')
            ->paginate();
    }
}
GET /users?fields[users]=id,name&fields[posts]=title&include=posts&filter[name]=john&sort=-created

Запрос выбирает users.id и users.name для пользователей и posts.title для их постов. Поскольку posts подгружается, в запрос постов добавляется posts.user_id, и каждый пользователь приходит с загруженными постами.

Исходный запрос ​

QueryBuilder::for() принимает:

  • класс модели: QueryBuilder::for(User::class);
  • Eloquent builder: QueryBuilder::for(User::where('active', true));
  • связь: QueryBuilder::for($team->users()).

HTTP-запрос берётся из контейнера. Другой можно передать вторым аргументом: QueryBuilder::for(User::class, $request).

Работа с результатом ​

QueryBuilder передаёт все остальные методы Eloquent builder, так что можно вызывать по цепочке where(), with(), скоупы и завершать её get(), first(), paginate(), simplePaginate(), cursorPaginate() и подобными:

php
$users = QueryBuilder::for(User::class)
    ->allowedFilters('name')
    ->where('active', true)
    ->get();

Фильтры и сортировки применяются при вызове allowedFilters() и allowedSorts(). Поля и include применяются непосредственно перед первым вызовом, читающим запрос. См. Отличия от spatie.

  • getEloquentBuilder() возвращает Eloquent builder со всем применённым.
  • getSubject() возвращает builder или связь в том виде, в каком их передали, без ожидающих применения полей и include.
  • clone() возвращает независимую копию, как и clone $query.

Ошибки ​

Неразрешённый параметр выбрасывает исключение, которое отображается как ответ 400:

ИсключениеКогда
InvalidFilterQueryнеизвестный фильтр
InvalidSortQueryнеизвестная сортировка
InvalidIncludeQueryнеизвестный include
InvalidFieldQueryнеизвестное поле
MalformedQueryParameterмассив там, где ожидается строка

Все они наследуют MyProgs\QueryBuilder\Exceptions\InvalidQuery, который является HttpException. Неизвестные фильтры, сортировки и include можно вместо этого игнорировать, см. Настройка.

Чтение запроса клиента ​

QueryBuilderRequest отдаёт разобранные параметры в виде коллекций — для кода, которому они нужны вне запроса:

php
use MyProgs\QueryBuilder\QueryBuilderRequest;

$request = QueryBuilderRequest::fromRequest(request());

$request->filters();   // ['name' => 'john']
$request->sorts();     // ['-created']
$request->includes();  // ['posts']
$request->fields();    // ['users' => ['id', 'name'], 'posts' => ['title']]

Имена и разделитель берутся из конфигурации query-builder.