项目作者: abdrzakoxa

项目描述 :
Make your laravel eloquent search scalable and simple
高级语言: PHP
项目地址: git://github.com/abdrzakoxa/laravel-eloquent-filter.git
创建时间: 2020-11-15T02:54:38Z
项目社区:https://github.com/abdrzakoxa/laravel-eloquent-filter

开源协议:MIT License

下载


Laravel Eloquent Filter


Tests
Total Downloads
Latest Stable Version
License

Scalable & secure way to filter laravel model

Introduction

Lets say we want to return a list of users filtered by multiple parameters. When we navigate to:

/users?name=avf&roles[]=admin&roles[]=manager&roles[]=client&limit=10

$request->all() will return:

  1. ['name' => 'avf', 'roles' => ['admin', 'manager', 'client'], 'limit' => '10']

To filter by all those parameters we would need to do something like:

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\User;
  4. use Illuminate\Database\Eloquent\Builder;
  5. use Illuminate\Http\Request;
  6. class UserController extends Controller
  7. {
  8. public function index(Request $request)
  9. {
  10. $query = User::query();
  11. $query->when($request->has('name'), function (Builder $builder) use ($request) {
  12. $builder->where('name', 'LIKE', '%'.$request->input('name').'%');
  13. });
  14. if (auth()->user()->isAdmin()) {
  15. $allowedRoles = ['admin', 'manager', 'client'];
  16. } elseif (auth()->user()->isManager()) {
  17. $allowedRoles = ['client'];
  18. } else {
  19. $allowedRoles = [];
  20. }
  21. $roles = [];
  22. foreach ((array) $request->input('roles') as $role) {
  23. if (in_array($role, $allowedRoles, true)) {
  24. $roles[] = $role;
  25. }
  26. }
  27. $query->whereHas('roles', function ($q) use ($roles) {
  28. return $q->whereIn('name', $roles);
  29. });
  30. if ($request->has('limit') && is_numeric($request->input('limit')) && $request->input('limit') < 100) {
  31. $limit = (int) $request->input('limit');
  32. } else {
  33. $limit = 10;
  34. }
  35. $query->limit($limit);
  36. return $query->get();
  37. }
  38. }

To filter that same input With Eloquent Filters:

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Models\User;
  4. use Illuminate\Http\Request;
  5. class UserController extends Controller
  6. {
  7. public function index(Request $request)
  8. {
  9. return User::filter($request->all())->get();
  10. }
  11. }

Installation

  1. composer require abdrzakoxa/laravel-eloquent-filter

Usage

Create your custom filter

create app/EloquentFilters/NameFilter.php file

  1. <?php
  2. namespace App\EloquentFilters;
  3. use Illuminate\Database\Eloquent\Builder;
  4. class NameFilter
  5. {
  6. /**
  7. * Apply the filter after validation passes & sanitize
  8. * @param string $value
  9. * @param Builder $builder
  10. */
  11. public function handle(string $value, Builder $builder): void
  12. {
  13. $builder->where('name', $value);
  14. }
  15. /**
  16. * @param mixed $value
  17. * @return mixed
  18. */
  19. public function sanitize($value)
  20. {
  21. return is_string($value) ? $value : '';
  22. }
  23. /**
  24. * @param mixed $value
  25. * @return bool|string|array
  26. */
  27. public function validate($value)
  28. {
  29. return strlen($value) > 5 && strlen($value) < 100;
  30. }
  31. }

Also, you can use only handle method

Apply NameFilter to a model

  1. <?php
  2. namespace App\Models;
  3. use App\EloquentFilters\NameFilter;
  4. use Abdrzakoxa\EloquentFilter\Traits\Filterable;
  5. use Illuminate\Database\Eloquent\Model;
  6. class User extends Model
  7. {
  8. use Filterable;
  9. protected $filters = [
  10. NameFilter::class,
  11. ];
  12. }

Available Filters

The following filters are available out of the box:

BetweenFilter

usage:

BetweenFilter is an available filter to filter between two dates

/users?approved_between[]=2020-10-03&approved_between[]=2020-11-03&created_between[]=2020-09-01&created_between[]=2020-12-01

  1. // ...
  2. use Abdrzakoxa\EloquentFilter\Traits\Filterable;
  3. use Abdrzakoxa\EloquentFilter\Filters\BetweenFilter;
  4. class User extends Model
  5. {
  6. use Filterable;
  7. protected $filters = [
  8. BetweenFilter::class . ':approved_at' => 'approved_between',
  9. BetweenFilter::class => 'created_between',
  10. ];
  11. }
  1. User::filter($request->all())->get();

LimitFilter

usage:

LimitFilter is an available filter to limit the final result

/users?limit=10

  1. // ...
  2. use Abdrzakoxa\EloquentFilter\Traits\Filterable;
  3. use Abdrzakoxa\EloquentFilter\Filters\LimitFilter;
  4. class User extends Model
  5. {
  6. use Filterable;
  7. protected $filters = [
  8. LimitFilter::class
  9. ];
  10. }
  1. User::filter($request->all())->get();

SortingFilter

usage:

LimitFilter is an available filter to sort the final result

/users?sorting=asc

  1. // ...
  2. use Abdrzakoxa\EloquentFilter\Traits\Filterable;
  3. use Abdrzakoxa\EloquentFilter\Filters\SortingFilter;
  4. class User extends Model
  5. {
  6. use Filterable;
  7. protected $filters = [
  8. SortingFilter::class . ':approved_at' // sorting by approved_at column
  9. ];
  10. }
  1. User::filter($request->all())->get();

Contributing

Any contributions welcome!