Improved filtering capabilities
This commit is contained in:
parent
82772f4310
commit
1f433ff42e
3 changed files with 59 additions and 37 deletions
|
|
@ -168,6 +168,7 @@ GET http://localhost/api.php/categories?filter=name,sw,Inter
|
|||
GET http://localhost/api.php/categories?filter=id,le,1
|
||||
GET http://localhost/api.php/categories?filter=id,ngt,2
|
||||
GET http://localhost/api.php/categories?filter=id,bt,1,1
|
||||
GET http://localhost/api.php/categories?filter=categories.id,eq,1
|
||||
```
|
||||
|
||||
Output:
|
||||
|
|
@ -176,6 +177,8 @@ Output:
|
|||
{"categories":{"columns":["id","name"],"records":[["1","Internet"]]}}
|
||||
```
|
||||
|
||||
NB: You may specify table name before the field name, seperated with a dot.
|
||||
|
||||
### List + Filter + Satisfy
|
||||
|
||||
Multiple filters can be applied by using "filter[]" instead of "filter" as a parameter name. Then the parameter "satisfy" is used to indicate whether "all" (default) or "any" filter should be satisfied to lead to a match:
|
||||
|
|
@ -183,6 +186,7 @@ Multiple filters can be applied by using "filter[]" instead of "filter" as a par
|
|||
```
|
||||
GET http://localhost/api.php/categories?filter[]=id,eq,1&filter[]=id,eq,3&satisfy=any
|
||||
GET http://localhost/api.php/categories?filter[]=id,ge,1&filter[]=id,le,3&satisfy=all
|
||||
GET http://localhost/api.php/categories?filter[]=id,ge,1&filter[]=id,le,3&satisfy=categories.all
|
||||
GET http://localhost/api.php/categories?filter[]=id,ge,1&filter[]=id,le,3
|
||||
```
|
||||
|
||||
|
|
@ -192,6 +196,8 @@ Output:
|
|||
{"categories":{"columns":["id","name"],"records":[["1","Internet"],["3","Web development"]]}}
|
||||
```
|
||||
|
||||
NB: You may specify "satisfy=categories.all,posts.any" if you want to mix "and" and "or" for different tables.
|
||||
|
||||
### List + Column selection
|
||||
|
||||
By default all columns are selected. With the "columns" parameter you can select specific columns. Multiple columns should be comma separated. An asterisk ("*") may be used as a wildcard to indicate "all columns":
|
||||
|
|
|
|||
76
api.php
76
api.php
|
|
@ -946,12 +946,7 @@ class PHP_CRUD_API {
|
|||
|
||||
protected function applyRecordFilter($callback,$action,$database,$tables,&$filters) {
|
||||
if (is_callable($callback,true)) foreach ($tables as $i=>$table) {
|
||||
$f = $this->convertFilters($callback($action,$database,$table));
|
||||
if ($f) {
|
||||
if (!isset($filters[$table])) $filters[$table] = array();
|
||||
if (!isset($filters[$table]['and'])) $filters[$table]['and'] = array();
|
||||
$filters[$table]['and'] = array_merge($filters[$table]['and'],$f);
|
||||
}
|
||||
$this->addFilters($filters,$table,array($table=>'and'),$callback($action,$database,$table));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -960,10 +955,8 @@ class PHP_CRUD_API {
|
|||
foreach ($keys as $field) {
|
||||
$v = $callback($action,$database,$table,$field->name);
|
||||
if ($v!==null) {
|
||||
if (!isset($filters[$table])) $filters[$table] = array();
|
||||
if (!isset($filters[$table]['and'])) $filters[$table]['and'] = array();
|
||||
if (is_array($v)) $filters[$table]['and'][] = $this->convertFilter($field->name,'in',implode(',',$v));
|
||||
else $filters[$table]['and'][] = $this->convertFilter($field->name,'eq',$v);
|
||||
if (is_array($v)) $this->addFilter($filters,$table,'and',$field->name,'in',implode(',',$v));
|
||||
else $this->addFilter($filters,$table,'and',$field->name,'eq',$v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1191,28 +1184,44 @@ class PHP_CRUD_API {
|
|||
return false;
|
||||
}
|
||||
|
||||
public function convertFilters($filters) {
|
||||
$result = array();
|
||||
if ($filters) {
|
||||
for ($i=0;$i<count($filters);$i++) {
|
||||
$parts = explode(',',$filters[$i],3);
|
||||
public function addFilter(&$filters,$table,$and,$field,$comparator,$value) {
|
||||
if (!isset($filters[$table])) $filters[$table] = array();
|
||||
if (!isset($filters[$table][$and])) $filters[$table][$and] = array();
|
||||
$filter = $this->convertFilter($field,$comparator,$value);
|
||||
if ($filter) $filters[$table][$and][] = $filter;
|
||||
}
|
||||
|
||||
public function addFilters(&$filters,$table,$satisfy,$filterStrings) {
|
||||
if ($filterStrings) {
|
||||
for ($i=0;$i<count($filterStrings);$i++) {
|
||||
$parts = explode(',',$filterStrings[$i],3);
|
||||
if (count($parts)>=2) {
|
||||
$field = $parts[0];
|
||||
if (strpos($parts[0],'.')) list($t,$f) = explode('.',$parts[0],2);
|
||||
else list($t,$f) = array($table,$parts[0]);
|
||||
$comparator = $parts[1];
|
||||
$value = isset($parts[2])?$parts[2]:null;
|
||||
$filter = $this->convertFilter($field,$comparator,$value);
|
||||
if ($filter) $result[] = $filter;
|
||||
$and = isset($satisfy[$t])?$satisfy[$t]:'and';
|
||||
$this->addFilter($filters,$t,$and,$f,$comparator,$value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function processFiltersParameter($tables,$satisfy,$filters) {
|
||||
$result = $this->convertFilters($filters);
|
||||
if (!$result) return array();
|
||||
$and = ($satisfy && strtolower($satisfy)=='any')?'or':'and';
|
||||
return array($tables[0]=>array($and=>$result));
|
||||
protected function processSatisfyParameter($tables,$satisfyString) {
|
||||
$satisfy = array();
|
||||
foreach (explode(',',$satisfyString) as $str) {
|
||||
if (strpos($str,'.')) list($t,$s) = explode('.',$str,2);
|
||||
else list($t,$s) = array($tables[0],$str);
|
||||
$and = ($s && strtolower($s)=='any')?'or':'and';
|
||||
$satisfy[$t] = $and;
|
||||
}
|
||||
return $satisfy;
|
||||
}
|
||||
|
||||
protected function processFiltersParameter($tables,$satisfy,$filterStrings) {
|
||||
$filters = array();
|
||||
$this->addFilters($filters,$tables[0],$satisfy,$filterStrings);
|
||||
return $filters;
|
||||
}
|
||||
|
||||
protected function processPageParameter($page) {
|
||||
|
|
@ -1231,9 +1240,7 @@ class PHP_CRUD_API {
|
|||
$this->convertOutputs($sql,$params,$fields[$table]);
|
||||
$sql .= ' FROM !';
|
||||
$params[] = $table;
|
||||
if (!isset($filters[$table])) $filters[$table] = array();
|
||||
if (!isset($filters[$table]['and'])) $filters[$table]['and'] = array();
|
||||
$filters[$table]['and'][] = $this->convertFilter($key[1],'eq',$key[0]);
|
||||
$this->addFilter($filters,$table,'and',$key[1],'eq',$key[0]);
|
||||
$this->addWhereFromFilters($filters[$table],$sql,$params);
|
||||
$object = null;
|
||||
if ($result = $this->db->query($sql,$params)) {
|
||||
|
|
@ -1289,9 +1296,7 @@ class PHP_CRUD_API {
|
|||
$params[] = $k;
|
||||
$params[] = $v;
|
||||
}
|
||||
if (!isset($filters[$table])) $filters[$table] = array();
|
||||
if (!isset($filters[$table]['and'])) $filters[$table]['and'] = array();
|
||||
$filters[$table]['and'][] = $this->convertFilter($key[1],'eq',$key[0]);
|
||||
$this->addFilter($filters,$table,'and',$key[1],'eq',$key[0]);
|
||||
$this->addWhereFromFilters($filters[$table],$sql,$params);
|
||||
$result = $this->db->query($sql,$params);
|
||||
if (!$result) return null;
|
||||
|
|
@ -1302,9 +1307,7 @@ class PHP_CRUD_API {
|
|||
$table = $tables[0];
|
||||
$sql = 'DELETE FROM !';
|
||||
$params = array($table);
|
||||
if (!isset($filters[$table])) $filters[$table] = array();
|
||||
if (!isset($filters[$table]['and'])) $filters[$table]['and'] = array();
|
||||
$filters[$table]['and'][] = $this->convertFilter($key[1],'eq',$key[0]);
|
||||
$this->addFilter($filters,$table,'and',$key[1],'eq',$key[0]);
|
||||
$this->addWhereFromFilters($filters[$table],$sql,$params);
|
||||
$result = $this->db->query($sql,$params);
|
||||
if (!$result) return null;
|
||||
|
|
@ -1467,13 +1470,14 @@ class PHP_CRUD_API {
|
|||
$callback = $this->parseGetParameter($get, 'callback', 'a-zA-Z0-9\-_');
|
||||
$page = $this->parseGetParameter($get, 'page', '0-9,');
|
||||
$filters = $this->parseGetParameterArray($get, 'filter', false);
|
||||
$satisfy = $this->parseGetParameter($get, 'satisfy', 'a-zA-Z');
|
||||
$satisfy = $this->parseGetParameter($get, 'satisfy', 'a-zA-Z0-9\-_,.');
|
||||
$columns = $this->parseGetParameter($get, 'columns', 'a-zA-Z0-9\-_,.*');
|
||||
$order = $this->parseGetParameter($get, 'order', 'a-zA-Z0-9\-_,');
|
||||
$transform = $this->parseGetParameter($get, 'transform', 't1');
|
||||
|
||||
$tables = $this->processTableAndIncludeParameters($database,$table,$include,$action);
|
||||
$key = $this->processKeyParameter($key,$tables,$database);
|
||||
$satisfy = $this->processSatisfyParameter($tables,$satisfy);
|
||||
$filters = $this->processFiltersParameter($tables,$satisfy,$filters);
|
||||
$page = $this->processPageParameter($page);
|
||||
$order = $this->processOrderParameter($order);
|
||||
|
|
@ -1608,9 +1612,7 @@ class PHP_CRUD_API {
|
|||
foreach ($select[$table] as $field => $path) {
|
||||
$values = $collect[$path[0]][$path[1]];
|
||||
if ($values) {
|
||||
if (!isset($filters[$table])) $filters[$table] = array();
|
||||
if (!isset($filters[$table]['and'])) $filters[$table]['and'] = array();
|
||||
$filters[$table]['and'][] = $this->convertFilter($field,'in',implode(',',$values));
|
||||
$this->addFilter($filters,$table,'and',$field,'in',implode(',',$values));
|
||||
}
|
||||
if ($first_row) $first_row = false;
|
||||
else echo ',';
|
||||
|
|
|
|||
|
|
@ -569,6 +569,20 @@ class PHP_CRUD_API_Test extends PHPUnit_Framework_TestCase
|
|||
$test->expect('{"posts":[{"category_id":"1","categories":[{"id":"1","name":"announcement"}]}]}');
|
||||
}
|
||||
|
||||
public function testFilterOnRelationAnd()
|
||||
{
|
||||
$test = new API($this);
|
||||
$test->get('/categories?include=posts&filter[]=id,ge,1&filter[]=id,le,1&filter[]=id,le,2&filter[]=posts.id,lt,8&filter[]=posts.id,gt,4');
|
||||
$test->expect('{"categories":{"columns":["id","name","icon"],"records":[["1","announcement",null]]},"posts":{"relations":{"category_id":"categories.id"},"columns":["id","user_id","category_id","content"],"records":[["5","1","1","#1"],["6","1","1","#2"],["7","1","1","#3"]]}}');
|
||||
}
|
||||
|
||||
public function testFilterOnRelationOr()
|
||||
{
|
||||
$test = new API($this);
|
||||
$test->get('/categories?include=posts&filter[]=id,ge,1&filter[]=id,le,1&filter[]=posts.id,eq,5&filter[]=posts.id,eq,6&filter[]=posts.id,eq,7&satisfy=all,posts.any');
|
||||
$test->expect('{"categories":{"columns":["id","name","icon"],"records":[["1","announcement",null]]},"posts":{"relations":{"category_id":"categories.id"},"columns":["id","user_id","category_id","content"],"records":[["5","1","1","#1"],["6","1","1","#2"],["7","1","1","#3"]]}}');
|
||||
}
|
||||
|
||||
public function testColumnsOnWrongInclude()
|
||||
{
|
||||
$test = new API($this);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue