Skip to content

Filters

plokko edited this page May 14, 2021 · 8 revisions

This package allows the user to filter returned data via defined parameters called filters.

Defining filters

Filters can be defined in the init method of the class

class ExampleQuerableResource extends ResourceQuery {

    protected function getQuery(): \Illuminate\Database\Eloquent\Builder
    {
        return User::where('id','>',0); // Just a simple query to demonstrate functionality
    }

    protected function init()
    {
        $this
            ->filter('name','like%')
            ->filter('email','%like%');
        //...
    }

}

or after its initialization

$qr = new ExampleQuerableResource();
$qr->filter('name','like%')
   ->filter('email','%like%');
//...
$query = User::select(['id','name','email'])->where('id','>',0);
$qr =  new ResourceQueryBuilder($query);
$qr->filter('name','like%')
   ->filter('email','%like%');

The init function will be called after the class constructor so any additional filters will be applied after.

Adding filters

Filters are composed of three main components: an unique filter name that will be used as query parameter, a condition that will be used to filter the data, and a field that specifies to what table field the filter will be applied.

You can add filters with the filter function by passing all the filter configuration or by adding it afterwards.

Note: if no field is specified the filter name will be automatically used as field (and will cause errors if not exists) and '=' will be used as a default condition.

$qr = new ExampleQuerableResource();
//You can specify all the basic filter parameter in the builder
$qr->filter('filter-name','=','table-field');
//or specify just the filter name and customize it afterwards
$qr->filter('filter-name2')
   ->field('table-field2');
   ->condition('%like%');

You can also add a filter with the filters->add method (alias to filter method)

//alias of $qr->filter(...)
$qr->filters->add('filter-label')->field('fieldA')->condition('=');

The previous functions will add a filter if not exists and edit it if it already exists without overwriting all the previous informations; If you want to re-define all the filter information you can use the fiters->set function.

$qr->filters->set('filter-label2')->field('fieldB')->condition('%like%');

Filter conditions

The filter condition can be either an SQL condition (like =,!=,<>,like,in, etc.), a shortand helper like like%,%like or %like% that will perform an SQL like compare adding a "%" character before, after or at both ends of the input, or a Callable function that will resolve the filter.

Example:

$qr
   ->filter('filter1')
      ->condition('=')//Will preforma a direct compare
   ->filter('filter2')
      ->condition('like')//Will perform a like
   ->filter('filter3')
      ->condition('>=')//Check if the field is greater than the value
   ->filter('filter4')
      ->condition('like%')//Check if the field start with the specified value
   ->filter('filter5')
      ->condition('%like%')//Check if the field contains the specified value
;

The Callable condition will have 3 parameters:

  1. \Illuminate\Database\Eloquent\Builder $query - The query where to apply the filter
  2. mixed $value - The filtered value
  3. FilterCondition $filter - The current filter, used to retrive condition or field name, etc.
$qr
   ->filter('filter1')
      ->condition(function($query,$value,$filter){
            $q->where('field1','>=',FilterCondition $value)
              ->orWhere('field2','<=',$value);//Just a basic example, you can do whatever you want to the query
            //you can retrieve field name by reading $filter->name
      });

Removing filters

You can remove a filter with

$qr->removeFilter('<filter-name>');
//Or
$qr->filters->remove('<filter-name>');

If you wish to remove all filters use

$qr->removeFilters();

or

$qr->filters->removeAll();

Additionally you can remove a filter using the unset function

unset($qr->filters['<filter-name>']);

Filter query parameter

Filters are passed as query parameters, to avoid query parameter conflicts they can be encapsulated as a query array (ex. "url?filter[name]=value1&filter[email]=value2" ) by defining it with setQueryParameter on the FilterBuilder

$qr->filters->setQueryParameter('filter');//<-- 'filter' will be used as the root query parameter 

By default 'filter' will be used as a query parameter, if the query parameter is set to null the root query parameter will be used (ex.: "url?name=value1&email=value2")

Additional filter options

Default filter value

If you want to apply a default value if the field is not present you can use defaultValue function:

$resource->filter('filter1','=','fieldA')->defaultValue('1234');//If filter "filter1" is not set it will be applied with value "123"

Value formatting

If you want to format the filter value (ex. escaping characters, capitalize, etc.) before the filter is applied you can add a callable function with the formatValue function. The original filter value will be passed as a parameter and the return value will be used as the new filter value.

Example:

$resource->filters->add('filter1','=','fieldA')->formatValue(function($value){ return trim($value); });

Apply only if another filter is present

If you want to apply a filter ONLY if one or more filters are present you can use applyIfPresent function

$resource->filters->add('filter1','=','fieldA');
$resource->filters->add('filter2','like','fieldB');
// If fitler1 or filter2 are empty fitler3 will be ignored
$resource->filters->add('filter3','=','fieldC')->applyIfPresent('filter1','filter2');

Apply only if another filter is absent

If you want to apply a filter ONLY if one or more filters are absent you can use applyIfNotPresent function

$resource->filters->add('filter1','=','fieldA');
$resource->filters->add('filter2','like','fieldB');
// If fitler1 or filter2 are not empty fitler3 will be ignored
$resource->filters->add('filter3','=','fieldC')->applyIfNotPresent('filter1','filter2');

Alternative filter defining methods

This library allows many ways to access and define the fiters: you can define condition and field directly on the add or set function

$resource->filters->add(<FILTER_NAME:string>,[<CONDITION:string|callable>],[<FIELD_NAME:string>]);
$resource->filters->set(<FILTER_NAME:string>,[<CONDITION:string|callable>],[<FIELD_NAME:string>]);

Or call it as a parameter, array or function (it will work like the add method)

// Called as a parameter
$qr->filters-><FILTER_NAME>;

// Accessed as an array
$qr->filters['<FILTER_NAME>'];
// Called as a function
$qr->filters-><FILTER_NAME>([<CONDITION:string|callable>],[<FIELD_NAME:string>]);

The add and set function can be called also on the condition allowing a fluent filter definition:

$qr->filters
     ->add('name')->field('name')->condition('like')
     ->add('email')->field('email')->condition('like'); //the add funtion will add a new filter and set the definition on the new one.