shureban / laravel-searcher
Laravel SDK for searching data in DB using requests
Installs: 2 702
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 1
Forks: 0
Open Issues: 0
Type:laravel-package
Requires
- php: ^8.1
README
Installation
Require this package with composer using the following command:
composer require shureban/laravel-searcher
Add the following class to the providers
array in config/app.php
:
Shureban\LaravelSearcher\SearcherServiceProvider::class,
You can also publish the config file to change implementations (i.e. interface to specific class).
php artisan vendor:publish --provider="Shureban\LaravelSearcher\SearcherServiceProvider"
How to use
By default, place your searchers in app\Http\Searchers folder.
Example with all searcher variations.
getQuery method
Should return query for applying filters. You may modify that
query Model::query()->with(['relation_1', 'relation_2' => fn() => ...])
getFilters method
Should return associative array where:
- keys must be equal to your request params
- values must be objects related of
\Shureban\LaravelSearcher\Searcher
Example
In that case:
- 'age' - is request parameter age
- 'client_age' - is DB column name
- new Between(...) - filter rule
return ['age' => new Between('client_age')];
class YourFirstSearcher extends Searcher { /** * @return Builder */ protected function getQuery(): Builder { return Model::query(); } /** * @return ColumnFilter[] */ protected function getFilters(): array { return [ //| Request param name | Filter object | Expected value type //------------------------------------------------------------------------- // Simple cases 'is_single' => new Boolean('is_single'), // bool 'age' => new Between('client_age'), // array (2 elements) 'salary' => new BetweenRange('salary'), // array (2 elements) 'birthday' => new BetweenDates('birthday'), // array (2 elements) 'id' => new Equal('id'), // any 'created_at' => new EqualDate('created_at'), // date 'height' => new Gt('height'), // number 'max_height' => new Gte('max_height'), // number 'updated_at' => new GtDate('updated_at'), // date 'deleted_at' => new GteDate('deleted_at'), // date 'statuses' => new In('status'), // array 'image_id' => new IsNull('image_id'), // bool 'email' => new Like('email'), // mixed 'foot_size' => new Lt('foot_size'), // number 'max_foot_size' => new Lte('max_foot_size'), // number 'birthday' => new LtDate('birthday'), // date 'hired_at' => new LteDate('hired_at'), // date 'partner_statuses' => new NotIn('partner_status'), // array 'only_every_even' => new Callback( fn(Builder $query, mixed $value) => $query->whereRaw('(id % 2 = 0)') ), // mixed // Modifier used. That case means, all rows where manager_id is equal to same value or null 'manager_id' => new OrNull(new Like('manager_id')), 'full_name' => new OrEmpty(new Like('full_name')), 'owner_id' => new MultipleOr(new Equal('user_id'), new Like('manager_id'), new Relation('brokers', new Equal('id'))), // Working with relation modifiers 'invoice_payouts' => new Relation('invoices', new Between('amount')), 'invoice_statuses' => new Relation('invoices', new In('status')), 'invoice_payment_method' => new Relation('invoices', new Like('payment_method')), 'invoice_process_statuses' => new Relation('invoices', new NotIn('process_status')), ]; } }
How to change Sorting
For change default sort column, you should override method sortColumn
.
protected function sortColumn(): ?string { return $this->request->get('sort_column', 'created_at'); }
If you need to change order behavior related with some column, do this. Override method applySortBy
protected function applySortBy(Builder $query, string $sortColumn, SortType $sortType): Builder { return match ($sortColumn) { 'your_special_column' => $query->orderBy('column_1', $sortType)->orderBy('column_2', $sortType), default => parent::applySortBy($query, $sortColumn, $sortType), }; }
Real case
Your first searcher
namespace App\Http\Searchers; use Illuminate\Database\Eloquent\Builder; use Shureban\LaravelSearcher\Filters\Like; use Shureban\LaravelSearcher\Searcher; class YourFirstSearcher extends Searcher { /** * @return Builder */ protected function getQuery(): Builder { return Model::query(); } /** * @return ColumnFilter[] */ protected function getFilters(): array { return [ 'id' => new Like('id'), ]; } }
Request
namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rules\Enum; use Illuminate\Validation\Rules\In; use Shureban\LaravelSearcher\Enums\SortType; class YourRequest extends FormRequest { /** * Get the validation rules that apply to the request. * * @return array */ public function rules(): array { return [ 'id' => ['int', 'min:1', 'max:2000000000'], 'sort_column' => [new In(['id'])], 'sort_type' => [new Enum(SortType::class)], ]; } }
Controller
namespace App\Http\Controllers; use Illuminate\Routing\Controller as BaseController; use App\Http\Requests\YourFirstSearcher; class YourController extends BaseController { /** * @param YourRequest $request * * @return JsonResponse */ public function __invoke(YourRequest $request): JsonResponse { $searcher = new YourFirstSearcher($request); // Collection with all models without pagination and slicing by per_page $allModels = $searcher->all(); // Collection contains per_page number of models and with page offset $models = $searcher->get(); // Base Laravel LengthAwarePaginator $paginator = $searcher->paginate(); return new JsonResponse($paginator); } }