Skip to content

Instantly share code, notes, and snippets.

@kingwill101
Last active February 22, 2023 05:51
Show Gist options
  • Save kingwill101/3a7a7a21682c960cab65c28042b32675 to your computer and use it in GitHub Desktop.
Save kingwill101/3a7a7a21682c960cab65c28042b32675 to your computer and use it in GitHub Desktop.
Laravel query builder filtering
<?php
namespace Api\Queries;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
trait QueryFilterTrait
{
/**
*
* Filter resources based on provided filters
*
* filters can be provided in several forms
* filter[{{resource_field_name}}]={{resource_field_value}}
* filter[{{resource_field_name}}][value]={{resource_field_value}}
*
* for advance lookups named filters can be used
*
* filter[{{custom-filter-name}}][condition][value]={{resource_field_value}}
* filter[{{custom-filter-name}}][condition][operator]= {{resource_field_operator}}
* filter[{{custom-filter-name}}][condition][path]={{resource_field_name}}
*
* or
*
* filter[{{custom-filter-name}}][condition][value]={{resource_field_value}}
* filter[{{custom-filter-name}}][condition][path]={{resource_field_name}}
*
*
* @param Builder $query
* @param array $params
* @param array $allowed_filters
* @param array $property_aliases
* @param array $allowed_operators
*/
public function parseFilters(Builder $query, array $params, array $allowed_filters = [], array $property_aliases = [], array $allowed_operators = ["lt", "lte", "gt", "gte", "eq", "like", "or"])
{
if (!isset($params["filter"]) || !is_array($params["filter"])) {
return;
}
$filters = $params["filter"];
foreach (array_keys($filters) as $key) {
$filtered = $filters[$key];
if (!isset($filtered)) {
continue;
}
if (!is_array($filtered)) {
if (!in_array($key, $allowed_filters) && !Arr::has($property_aliases, $key)) {
continue;
}
//filter[status]=1
$this->where($query, Arr::has($property_aliases, $key) ?
Arr::get($property_aliases, $key) : $key, "=",
$filtered);
continue;
}
if (isset($filtered["value"])) {
//short version
//filter[status][value]=1
if (!in_array($key, $allowed_filters) && !Arr::has($property_aliases, $key)) {
continue;
}
$key = Arr::has($property_aliases, $key) ? Arr::get($property_aliases, $key) : $key;
$this->where($query, $key, "=", $filtered["value"]);
} else if (isset($filtered["condition"])) {
//long version(named filters)
$value = $filtered["condition"]["value"] ?? null;
$operator = $filtered["condition"]["operator"] ?? null;
$path = $filtered["condition"]["path"] ?? null;
if (!isset($path) && (!Arr::has($allowed_filters, $path) || !Arr::has($property_aliases, $path))) {
continue;
}
$path = Arr::has($property_aliases, $path) ? Arr::get($property_aliases, $path) : $path;
if (isset($operator) && isset($value)) {
//filter[status-filter][condition][value]=1
//filter[status-filter][condition][operator]= 'eq'
//filter[status-filter][condition][path]=status
if (!in_array($operator, $allowed_operators)) {
continue;
}
switch ($operator) {
case "lt":
$this->where($query, $path, "<", $value);
break;
case "lte":
$this->where($query, $path, "<=", $value);
break;
case "gt":
$this->where($query, $path, ">", $value);
break;
case "gte":
$this->where($query, $path, ">=", $value);
break;
case "eq":
$this->where($query, $path, "=", $value);
break;
case "or":
$this->where($query, $path, "=", $value, true);
break;
case "like":
$this->where($query, $path, "like", "%" . $value . "%");
break;
default:
break;
}
} else if (isset($value)) {
//filter[status-filter][condition][value]=1
//filter[status-filter][condition][path]=status
$this->where($query, $path, "=", $value);
}
}
}
}
private function where(Builder $query, $col, $operator, $value, bool $or = false)
{
if (in_array($col, $query->getModel()->getDates())) {
if ($or) {
$query->orWhereDate($col, $operator, Carbon::parse($value));
return;
}
$query->whereDate($col, $operator, Carbon::parse($value));
return;
}
if ($or) {
$query->orWhere($col, $operator, $value);
return;
}
$query->where($col, $operator, $value);
}
}
@kingwill101
Copy link
Author

Updated to handle the querying of date fields

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