@thepsion5
thanks! That way sounds like you could end up with tonnes of different methods. Is this a possible way to handle it:
<?php
namespace Storage;
use StdClass;
trait FilterableTrait {
protected $validFilterableFields = ['sort', 'page', 'created_at', 'modified_at'];
protected $filters = [];
protected $model;
protected function addFilter($field, $value, $operator='=')
{
if($value == null) return false;
$this->filters[$field] = array(
'value' => $value,
'operator' => $operator
);
return true;
}
public function applyFiltersToQuery()
{
foreach ($this->filters as $field => $value_operator) {
$value = $value_operator['value'];
$operator = $value_operator['operator'];
if($operator == 'page') continue;
if(is_array($value)) {
$this->model = $this->model->where(function($query) use($value, $field, $operator) {
foreach ($value as $val) {
$controls = $this->applyFilterToQuery($field, $val, $operator, 'OR', true);
if(isset($controls['operator'])) {
$query->$controls['queryType']($controls['field'], $controls['operator'], $controls['value']);
} else {
$query->$controls['queryType']($controls['field'], $controls['value']);
}
}
});
} else {
$this->model = $this->applyFilterToQuery($field, $value, $operator);
}
}
return $this;
}
public function applyFilterToQuery($field, $val, $operator, $connector = 'AND', $returnArray = false)
{
$clause = $connector == 'OR' ? 'orWhere' : 'where';
switch($operator) {
case '=' :
case '>' :
case '<' :
case '<=' :
case '>=' :
case '<>' :
if($returnArray) {
return [
'queryType' => $clause,
'operator' => $operator,
'field' => $field,
'value' => $val
];
}
return $this->model = $this->model->$clause($field, $operator, $val);
break;
case 'sort' :
$direction = substr($val, 0, 4) == 'asc_' ? 'asc' : 'desc';
if(substr($val, 0, 5) == 'desc_' or $direction == 'asc') {
$orderAgainst = substr($val, strlen($direction) + 1);
if(!in_array($orderAgainst, $this->validFilterableFields)) return $this->model;
if($returnArray) {
return [
'queryType' => 'orderBy',
'field' => $orderAgainst,
'value' => $direction
];
}
return $this->model = $this->model->orderBy($orderAgainst, $direction);
} else {
if(!in_array($val, $this->validFilterableFields)) return $this->model;
if($returnArray) {
return [
'queryType' => 'orderBy',
'field' => $val,
'value' => $direction
];
}
return $this->model = $this->model->orderBy($val, $direction);
}
break;
}
}
public function addFilters($filters)
{
foreach ($filters as $field => $value) {
$operator = '=';
$fieldPrefix = substr($field, 0, 3);
if(substr($field, 3, 1) == '_') {
switch($fieldPrefix) {
case 'gtn' : //greater than
$operator = '>';
$field = substr($field, 4);
break;
case 'gte' : //greater than or equal to
$operator = '>=';
$field = substr($field, 4);
break;
case 'gtd' : //greater than date
$operator = '>';
$field = substr($field, 4);
$value = date('Y-m-d H:i:s', strtotime($value));
break;
case 'ltn' : //less than
$operator = '<';
$field = substr($field, 4);
break;
case 'lte' : //less than or equal to
$operator = '<=';
$field = substr($field, 4);
break;
case 'ltd' : //less than date
$operator = '<';
$field = substr($field, 4);
$value = date('Y-m-d H:i:s', strtotime($value));
break;
case 'not' : //not equal to
$operator = '<>';
$field = substr($field, 4);
break;
}
}
if($operator <> '=') {
if(!in_array($field, $this->validFilterableFields)) return $this->model;
}
if($field == 'sort') $operator = 'sort';
if($field == 'page') $operator = 'page';
$this->addFilter($field, $value, $operator);
}
return $this->applyFiltersToQuery();
}
public function all() {
return $this->model = $this->applyFiltersToQuery();
}
public function find($id) {
return $this->model = $this->model->find($id)->get();
}
public function getByPage($page = 1, $limit = 5)
{
$results = new StdClass;
$results->page = $page;
$results->limit = $limit;
$results->totalItems = 0;
$results->items = array();
$this->model = $this->model->skip($limit * ($page - 1))->take($limit)->get();
$results->totalItems = $this->model->count();
$results->items = $this->model;
return $results;
}
}
Basically, ?lte_age=18¬_name=james&sort=asc_name
Would return all results:
WHERE
age <= 18 AND
name <> 'james'
ORDER BY name
ASC