Laravel Filter Scope on a Model
So I find myself writing searchable pages that, via an API or what not, someone can filter the page by different fields on the model.
This can end up being a Controller class that does a lot of filters off the Request. Or it can be a Repository class that abstracts the business logic into one place for several related models.
But in many cases it really is just one Model being filtered. And if I add a Scope scopeFilter
and pass in the Request as an array I can iterate over that array and call to other existing scopes on the model.
/**
* Return only active models
*
* @param object $query
* @param array $filters
* @return Builder
*/
public function scopeFilters($query, $filters)
{
unset($filters['page']);
foreach ($filters as $scope => $value) {
$scope = camel_case($scope);
$query = $this->{$scope}($value);
}
return $query;
}
This allows me to use those scopes in other places as well.
For example a request to active policies for repo_name “foo”:
curl https://foo.test/api/policies?active=1&repo_name=foo
The Controller can do something simple like this:
public function __invoke(Request $request)
{
try {
$results = Subscriber::filters($request->all())->orderBy("repo_name")->paginate(20);
return response()->json($results, 200);
} catch (\Exception $e) {
\Log::error($e);
return response()->json(null, 400);
}
}
And the model can handle it with these other scopes, that can be used by themselves as well:
/**
* Scope to get by repo_name
*
* @param object $query
* @param string $repo_name
* @return Builder
*/
public function scopeRepoName($query, $repo_name)
{
return $query->where("repo_name", $repo_name);
}
/**
* Return only active models
*
* @param object $query
* @return Builder
*/
public function scopeActive($query, $state = 1)
{
if ($state == 'all') {
$state = [0,1];
}
$state = array_wrap($state);
return $query->whereIn("active", $state);
}
For some time I kept this logic out of models but recently I been trying to use models as more of a place to store this sort of model related logic.
If two models need to work together then maybe a Business class could help out to glue them together but still something to consider.
I will show in the next post one model subscribing another model.
comments powered by Disqus