Zostavenie dopytu
Vytvorte dopyt pre model (alebo pripravený builder), deklarujte allow-list a s výsledkom pracujte ako s bežným Eloquent builderom — neznáme volania sa prepošlú priamo ďalej:
use RoundlyConsulting\QueryBuilder\AllowedFilter;
use RoundlyConsulting\QueryBuilder\AllowedSort;
use RoundlyConsulting\QueryBuilder\QueryBuilder;
$posts = QueryBuilder::for(Post::class)
->allowedFilters(
AllowedFilter::exact('status'),
AllowedFilter::partial('title'),
AllowedFilter::scope('published', booleans: true),
AllowedFilter::callback('min_views', fn ($query, $value) => $query->where('views', '>=', $value)),
AllowedFilter::trashed(),
)
->allowedSorts('title', AllowedSort::field('popularity', 'views'))
->defaultSort('-created_at')
->with(['author'])
->paginate($request->perPage());Vstupný bod
QueryBuilder::for(string|Builder $subject, ?Request $request = null) prijme názov triedy modelu alebo pripravený Eloquent builder, takže dopyt môžete vopred zúžiť. Voliteľný druhý argument určuje request, z ktorého sa číta — predvolene aktuálny request():
// A model class — starts from Post::query()
QueryBuilder::for(Post::class);
// A prepared builder — its constraints are kept
QueryBuilder::for(Post::query()->where('active', true));
// An explicit request (tests, jobs, sub-requests) instead of request()
QueryBuilder::for(Post::class, $request);V controlleri
Typický zoznamový endpoint spája builder s FormRequestom, ktorý validuje veľkosť stránky (pozri Stránkovanie):
namespace App\Http\Controllers;
use App\Http\Requests\ListPostsRequest;
use App\Models\Post;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use RoundlyConsulting\QueryBuilder\AllowedFilter;
use RoundlyConsulting\QueryBuilder\QueryBuilder;
final class PostController
{
public function index(ListPostsRequest $request): LengthAwarePaginator
{
return QueryBuilder::for(Post::class)
->allowedFilters('status', AllowedFilter::partial('title'))
->allowedSorts('title', 'created_at')
->defaultSort('-created_at')
->with(['author'])
->paginate($request->perPage());
}
}Request na tento endpoint:
GET /posts?filter[status]=published&filter[title]=laravel&sort=-created_at,title&page=2&per_page=25Ako sa aplikuje
- Skratka — reťazec v allowedFilters() sa zmení na AllowedFilter::exact(), v allowedSorts() na AllowedSort::field().
- Lenivo a raz — filtre a triedenia sa aplikujú pri prvom volaní, ktoré sa prepošle builderu (get, paginate, with, where, …), alebo pri getEloquentBuilder(), a nikdy nie dvakrát.
- Transparentné preposielanie — preposlané volanie, ktoré vráti builder, vráti samotný QueryBuilder, takže reťazenie pokračuje; čokoľvek iné (kolekcia, paginator, model) sa vráti bez zmeny.
- getEloquentBuilder() — vráti podkladový Eloquent builder s aplikovanými filtrami a triedeniami pre kód, ktorý potrebuje skutočnú inštanciu Builder.
$builder = QueryBuilder::for(Post::class)
->allowedFilters('status')
->allowedSorts('title')
->getEloquentBuilder(); // Illuminate\Database\Eloquent\Builder, filters + sorts applied
$count = $builder->count();Allow-list deklarujte ako prvý
allowedFilters(), allowedSorts() a defaultSort() deklarujte pred akýmkoľvek volaním buildera. Request sa aplikuje pri prvom volaní, ktoré sa prepošle builderu, pretože práve to volanie môže dopyt spustiť. Deklarácia po tomto bode vyhodí AllowListAlreadyApplied (LogicException) namiesto toho, aby sa potichu ignorovala — bez ohľadu na obsah requestu, takže zle zoradená reťaz zlyhá už pri vývoji, nie až pri prvom klientovi, ktorý filtruje:
QueryBuilder::for(Post::class)
->allowedFilters('status') // declare first…
->where('views', '>', 0) // …then any builder call
->get();
QueryBuilder::for(Post::class)
->where('views', '>', 0)
->allowedFilters('status'); // throws AllowListAlreadyApplied
// Constraints that must exist before the request is applied go on the builder you pass in
QueryBuilder::for(Post::query()->where('views', '>', 0));Čo necháva na vás
Balík rieši len filtrovanie, triedenie a stránkovanie. Správa includov a eager loadingu, sparse fieldsets, pridané atribúty a cursor stránkovanie sú zámerne mimo rozsahu — balík také parametre z requestu nečíta. Eager loading riešte v kóde cez with() ako zvyčajne.
Prejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.