anourvalar / eloquent-request
Dynamic Query Builder based on request
2.10.13
2026-06-12 13:58 UTC
Requires
- php: ^8.2
- anourvalar/laravel-atom: ^2.24
- laravel/framework: ^8.0|^9.0|^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.26
- orchestra/testbench: ^9.0|^10.0|^11.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
- squizlabs/php_codesniffer: ^3.7
This package is auto-updated.
Last update: 2026-06-12 13:59:07 UTC
README
- Filling up the QueryBuilder from user data. Key feature is safety: all data is under a validation.
- Profile-based approach limit access to the columns and operations.
Installation
composer require anourvalar/eloquent-request
Usage: basic
Request
{
"filter": {
"created_at": {">": "2021-01-01"}
},
"sort": {
"created_at": "DESC"
}
}
Code
class UserController extends Controller { /** * Profile */ protected $profile = [ 'filter' => [ 'created_at' => ['=', '!=', '<', '<=', '>', '>=', 'in', 'not-in'], ], 'sort' => ['created_at'], ]; /** * Users list */ public function index(Request $request) { $users = \App::make(\AnourValar\EloquentRequest\Service::class)->buildBy( \App\User::class, $this->profile, $request->input() ); // Equals to: // \App\User // ::where('created_at', '>', '2021-01-01') // ->orderBy('created_at', 'DESC') // ->paginate($request->input('page')); } }
Usage: relations & QueryBuilder preconfigure
Request
{
"filter": {
"userPhones.phone_number": {"like": "1234"}
}
}
Code
class UserController extends Controller { /** * Profile */ protected $profile = [ 'filter' => [ 'userPhones.phone_number' => ['like'], ], ]; /** * Users list */ public function index(Request $request) { $users = \App::make(\AnourValar\EloquentRequest\Service::class)->buildBy( \App\User::where('status', '=', 'active'), $this->profile, $request->input() ); // Equals to: // \App\User // ::where('status', '=', 'active') // ->whereHas('userPhones', function ($query) // { // $query->where('phone_number', 'like', '%1234%'); // }) // ->paginate($request->input('page')); } }
Usage: simple pagination
Code
class UserController extends Controller { /** * Profile */ protected $profile = [ 'options' => [ \AnourValar\EloquentRequest\Actions\PaginateAction::OPTION_SIMPLE_PAGINATE, \AnourValar\EloquentRequest\Actions\PaginateAction::OPTION_PAGE_MAX => 20, ], ]; /** * Users list */ public function indexAny() { $list = $this->buildBy( \App\User::whereNotNull('email_verified_at') ); // Equals to: \App\User::whereNotNull('email_verified_at')->simplePaginate($request->input('page')); } }
Usage: advanced features
Code
class UserController extends Controller { use \AnourValar\EloquentRequest\ControllerTrait; // helper for quick usage /** * Profile */ protected $profile = [ 'filter' => [ 'created_at' => \AnourValar\EloquentRequest\Events\RequestBuiltEvent::PROFILE_FILTER_DATE, // preset ], 'ranges' => [ 'created_at' => ['min' => '2018-01-01'], // filter's constrainment ], 'scope' => [ 'customStuff', // Eloquent scope ], 'sort' => ['created_at'], ]; /** * Users list */ public function indexAny() { $users = $this->buildBy(\App\User::where('status', '=', 'active')); } }
Usage: via facade
Code
$profile = [ 'filter' => [ 'id' => ['in'], ], ]; $request = [ 'filter' => ['id' => ['in' => [1,2,3]]], ]; $collection = \EloquentRequest::buildBy(\App\User::class, $profile, $request);
Usage: Flat table
Setup
Model Observer (saved, deleted):
\EloquentRequestFlat::sync(\App::make(\App\Drivers\ModelFlat::class), $model);
Migration (up):
\EloquentRequestFlat::createTable(\App::make(\App\Drivers\ModelFlat::class));
Migration (down):
\EloquentRequestFlat::dropTable(\App::make(\App\Drivers\ModelFlat::class));
"Simple" workflow
Config:
'flat' => [ 'shadow' => false, ],
Seeder:
if (! \EloquentRequestFlat::isActualTable($flatInterface)) { \EloquentRequestFlat::createTable($flatInterface); \EloquentRequestFlat::resync($flatInterface, \App\Model::class); }
"Shadow" workflow
Config:
'flat' => [ 'shadow' => true, // it's recommended to false when the structure is permanent ],
Seeder:
if (! \EloquentRequestFlat::isActualTable($flatInterface)) { \EloquentRequestFlat::createTable($flatInterface); }
After deploy:
if (\EloquentRequestFlat::shadow($flatInterface)) { $closure = function ($flatInterface, $model) { \DB::transaction(function () use ($flatInterface, $model) { // Atomic lock (for sync): // <...> $this->syncSoft($flatInterface, $model->fresh()); }); }; \EloquentRequestFlat::resync($flatInterface, \App\Model::class, $closure); \DB::transaction(function () use ($flatInterface) { // Atomic lock (for sync): // <...> \EloquentRequestFlat::switchShadow($flatInterface); }); }