Created
December 6, 2019 15:07
-
-
Save AlexVanderbist/043a6065e43eda616148315ef02583c7 to your computer and use it in GitHub Desktop.
laravel-query-builder scope filter with model binding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 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
Can you have example of how use this scope ?