Основы использования
Spatie-совместимый API — это класс QueryBuilder. Он оборачивает Eloquent-запрос и применяет параметры запроса клиента, которые вы разрешили:
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() и подобными:
$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 отдаёт разобранные параметры в виде коллекций — для кода, которому они нужны вне запроса:
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.