Query filter
daravel_teorion mengubah query string sebuah listing menjadi filter, eager
load, count, sort, dan pagination, dalam whitelist yang Anda deklarasikan
sekali per model. Paket ini adalah port dari
laravel-teorion
dengan format request yang sama, sehingga satu client bisa dipakai untuk API
Laravel maupun Daravel.
dart pub add daravel_teorion
dartisan make:query-filter Post
// lib/app/query_filters/post_query_filter.dart
final class PostQueryFilter extends QueryFilter<Post> {
@override
Map<String, Filter> get filters => {
'search': Filter.multiLike(['title', 'body']).alias('q'),
'status': Filter.enum_('status', PostStatus.values),
'is_active': Filter.boolean().withDefault(true),
'author_id': Filter.exact(),
'has_comments': Filter.has('comments'),
};
@override
List<String> get allowedScopes => ['published', 'popular'];
@override
List<String> get allowedWiths => ['author', 'tags'];
@override
List<String> get allowedWithCounts => ['comments'];
@override
List<String> get allowedSorts => ['created_at', 'title', 'views'];
@override
List<String> get defaultSort => ['-created_at'];
}
make:query-filter mendaftarkannya di bootstrap/query_filters.dart;
berikan map itu ke aplikasi, dan controller cukup satu baris:
Application.configure(basePath: basePath).withQueryFilters(queryFilters)
router.get('/posts', (request) => Post.definition.query().filterAndPaginate(request));
router.get('/posts/{id}', (request) =>
Post.definition.query().findFiltered(request, request.param<String>('id')));
Model juga bisa menyebut filternya sendiri (with Filterable<Post> dan
newQueryFilter()), dan setiap pemanggilan bisa memberikan filter:
filterAndPaginate(request, AdminPostQueryFilter()). filter(request)
mengembalikan query, untuk dilanjutkan dengan .where(...), .get(), atau
.first().
Request#
| Parameter | Contoh | Efek |
|---|---|---|
| Filter yang dideklarasikan | ?q=dart&status=published |
Diterapkan bila ada (atau dengan default-nya) |
scopes[] |
?scopes[]=published |
Scope model, diberi seluruh request |
scopes[N] |
?scopes[0][name]=byAuthor&scopes[0][params][author_id]=3 |
Scope, hanya diberi parameternya sendiri |
withs[] |
?withs[]=author&withs[]=author.country |
Eager load (segmen pertama harus diizinkan) |
withs[] dengan kolom |
?withs[]=author:id,name |
Hanya kolom-kolom itu, bila allowedWithColumns mendaftarnya |
withCounts[] |
?withCounts[]=comments |
comments_count |
withAggregates |
?withAggregates[comments][sum][]=score |
comments_sum_score (juga avg, min, max, count) |
sort |
?sort=-created_at,title |
- untuk menurun |
order[N], order_by |
?order_by=title&order_direction=desc |
Format lama |
order_null_bottoms[] |
?order_null_bottoms[]=published_at |
NULL di akhir |
is_paginate, per_page |
?is_paginate=1&per_page=20 |
Satu halaman (LengthAwarePaginator), bukan semua baris |
pagination=cursor, cursor |
?pagination=cursor&per_page=20 |
CursorPaginator |
max_results |
?max_results=5 |
Paling banyak sejumlah itu, tanpa paging |
with_trashed, only_trashed |
?with_trashed=1 |
Pada model yang memakai soft delete |
visibles[], hiddens[] |
?hiddens[]=email |
Menampilkan atau menyembunyikan atribut |
Tanpa is_paginate atau pagination, semua baris yang cocok dikembalikan,
seperti di laravel-teorion (10 per halaman secara default saat paging,
TEORION_DEFAULT_PER_PAGE).
Kolom sort atau scope di luar whitelist dijawab 400 dengan pesan dari
laravel-teorion (Sort column [password] is not in the allowed sorts list.), begitu pula filter wajib yang tidak ada. Relasi di luar
allowedWiths, dan scope yang diizinkan tetapi tidak didefinisikan model,
dilewati, kecuali TEORION_STRICT (default mengikuti APP_DEBUG) juga
menolaknya.
Client hanya bisa memilih kolom sebuah relasi dari kolom yang Anda daftar,
per path relasi; relasi tanpa daftar dimuat utuh dan permintaan kolom
untuknya ditolak, begitu pula kolom lain (Column [password] of relation [author] is not in the allowed with columns list. dalam mode strict). Key
yang dipakai relasi untuk mencocokkan ditambahkan, sehingga author:name
tetap menemukan author-nya.
@override
Map<String, List<String>> get allowedWithColumns => {
'author': ['id', 'name', 'avatar'],
'author.country': ['name'],
};
Filter#
| Filter | SQL |
|---|---|
Filter.exact() |
col = ? |
Filter.like(), Filter.multiLike([...]) |
col LIKE %?%, (a LIKE %?% OR b LIKE %?%) |
Filter.boolean() |
col = 1 atau 0 |
Filter.null_() |
col IS NOT NULL untuk nilai true, IS NULL selain itu |
Filter.enum_(col, values) |
col = ? untuk salah satu values; nilai lain tidak cocok dengan apa pun |
Filter.in_() |
col IN (...) dari a,b atau col[]=a&col[]=b |
Filter.date(), Filter.dateRange(col, 'start_date', 'end_date') |
DATE(col) = ?, col BETWEEN ? AND ? |
Filter.between(), Filter.range() |
BETWEEN dari a,b; >=/<= dari <param>_min / <param>_max |
Filter.gt(col, orEqual), Filter.lt(...) |
col > ?, col < ? |
Filter.has('comments') |
EXISTS / NOT EXISTS |
Filter.jsonContains() |
whereJsonContains(col, value) |
Filter.callback((query, value, param, request) {...}) |
Milik Anda |
Filter.scope('name'), Filter.macro('name') |
Scope model; tipe yang didaftarkan dengan FilterMacroRegistry.register |
Masing-masing menerima .alias('q'), .withDefault(value), dan
.required(). Nama dengan garis bawah (enum_, in_, null_) menghindari
keyword Dart.
Validasi, dokumentasi, dan audit#
PostQueryFilter().validationRules memberi form request aturan untuk
parameter listing dan setiap filter (HasQueryFilterRules dari
laravel-teorion); openApiParameters mendeskripsikannya untuk referensi
API.
Dengan TEORION_AUDIT_ENABLED=true, setiap listing mengirim QueryAudited
berisi fingerprint (SHA-256 dari filter, model, dan parameter request, tanpa
memedulikan urutan dan halamannya), mode terminal, jumlah hasil, durasi,
dan user; TEORION_AUDIT_LOG juga mencatatnya ke log, dan
TEORION_AUDIT_SAMPLE_RATE mengaudit sebagian fingerprint, selalu yang
sama.
Perbedaan dengan laravel-teorion#
order_null_bottoms[]hanya menerima kolom sort yang diizinkan, dengan quoting; laravel-teorion menulis nilainya ke SQL apa adanya.withs[]=relation:columnshanya menerima kolom yang didaftarallowedWithColumns; laravel-teorion meneruskan kolom apa pun, termasuk yang tersembunyi.Filter.range()danFilter.dateRange()berlaku saat parameternya sendiri ada (views_min,start_date); laravel-teorion juga butuh parameter yang dideklarasikan itu sendiri.- Penolakan berupa 400, bukan 500.