Skip to content

Instantly share code, notes, and snippets.

@AlexVanderbist
Created December 6, 2019 15:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexVanderbist/043a6065e43eda616148315ef02583c7 to your computer and use it in GitHub Desktop.
Save AlexVanderbist/043a6065e43eda616148315ef02583c7 to your computer and use it in GitHub Desktop.
laravel-query-builder scope filter with model binding
<?php
namespace App\Http\Filters;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use ReflectionObject;
use Spatie\QueryBuilder\Filters\Filter;
class ScopeFilter implements Filter
{
public function __invoke(Builder $query, $values, string $property): Builder
{
$scope = Str::camel($property);
$values = Arr::wrap($values);
$values = $this->replaceValuesWithModels($query, $scope, $values);
return $query->$scope(...$values);
}
protected function replaceValuesWithModels(Builder $query, string $scope, array $values): array
{
$scopeParameters = (new ReflectionObject($query->getModel()))
->getMethod('scope' . ucfirst($scope))
->getParameters();
foreach ($scopeParameters as $scopeParameter) {
if (! $scopeParameter->getClass()->isSubclassOf(Model::class)) {
continue;
}
$model = $scopeParameter->getClass()->newInstance();
$index = $scopeParameter->getPosition() - 1;
$value = $values[$index];
if (is_numeric($value)) {
$values[$index] = $model::find($value);
}
}
return $values;
}
}
@welmarr
Copy link

welmarr commented Apr 5, 2022

Can you have example of how use this scope ?

@AlexVanderbist
Copy link
Author

AlexVanderbist commented Apr 5, 2022

@welmarr It's been a while but this should do the trick:

QueryBuilder::for(User::class)->allowedFilters(ScopeFilter::class)->get();

The request the looks like this: GET /users?filters[scope_name_in_camel_case]=scope-value-to-query

Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment