Browse Source

Sort on multiple fields #162

Maurits van der Schee 7 years ago
parent
commit
5e1ea8a1bb
3 changed files with 47 additions and 26 deletions
  1. 3
    0
      README.md
  2. 28
    24
      api.php
  3. 16
    2
      tests/tests.php

+ 3
- 0
README.md View File

224
 
224
 
225
 ```
225
 ```
226
 GET http://localhost/api.php/categories?order=name,desc
226
 GET http://localhost/api.php/categories?order=name,desc
227
+GET http://localhost/api.php/posts?order[]=icon,desc&order[]=name
227
 ```
228
 ```
228
 
229
 
229
 Output:
230
 Output:
232
 {"categories":{"columns":["id","name"],"records":[[3,"Web development"],[1,"Internet"]]}}
233
 {"categories":{"columns":["id","name"],"records":[[3,"Web development"],[1,"Internet"]]}}
233
 ```
234
 ```
234
 
235
 
236
+NB: You may sort on multiple fields by using "order[]" instead of "order" as a parameter name.
237
+
235
 ### List + Order + Pagination
238
 ### List + Order + Pagination
236
 
239
 
237
 The "page" parameter holds the requested page. The default page size is 20, but can be adjusted (e.g. to 50):
240
 The "page" parameter holds the requested page. The default page size is 20, but can be adjusted (e.g. to 50):

+ 28
- 24
api.php View File

187
 		return "$sql LIMIT $limit OFFSET $offset";
187
 		return "$sql LIMIT $limit OFFSET $offset";
188
 	}
188
 	}
189
 
189
 
190
-	public function addOrderByDifferenceToSql($sql,$field,$direction) {
191
-		if ($this->isGeometryType($field)) {
192
-			return "$sql ORDER BY ST_Distance(!, ?) $direction";
193
-		} else {
194
-			return "$sql ORDER BY ABS(! - ?) $direction";
195
-		}
196
-	}
197
-
198
 	public function likeEscape($string) {
190
 	public function likeEscape($string) {
199
 		return addcslashes($string,'%_');
191
 		return addcslashes($string,'%_');
200
 	}
192
 	}
1126
 		return array($key,$fields[0]);
1118
 		return array($key,$fields[0]);
1127
 	}
1119
 	}
1128
 
1120
 
1129
-	protected function processOrderParameter($order) {
1130
-		if (!$order) return false;
1131
-		$order = explode(',',$order,2);
1132
-		if (count($order)<2) $order[1]='ASC';
1133
-		if (!strlen($order[0])) return false;
1134
-		$order[1] = strtoupper($order[1])=='DESC'?'DESC':'ASC';
1135
-		return $order;
1121
+	protected function processOrderingsParameter($orderings) {
1122
+		if (!$orderings) return false;
1123
+		foreach ($orderings as &$order) {
1124
+			$order = explode(',',$order,2);
1125
+			if (count($order)<2) $order[1]='ASC';
1126
+			if (!strlen($order[0])) return false;
1127
+			$direction = strtoupper($order[1]);
1128
+			if (in_array($direction,array('ASC','DESC'))) {
1129
+				$order[1] = $direction;
1130
+			}
1131
+		}
1132
+		return $orderings;
1136
 	}
1133
 	}
1137
 
1134
 
1138
 	protected function convertFilter($field, $comparator, $value) {
1135
 	protected function convertFilter($field, $comparator, $value) {
1546
 		$filters   = $this->parseGetParameterArray($get, 'filter', false);
1543
 		$filters   = $this->parseGetParameterArray($get, 'filter', false);
1547
 		$satisfy   = $this->parseGetParameter($get, 'satisfy', 'a-zA-Z0-9\-_,.');
1544
 		$satisfy   = $this->parseGetParameter($get, 'satisfy', 'a-zA-Z0-9\-_,.');
1548
 		$columns   = $this->parseGetParameter($get, 'columns', 'a-zA-Z0-9\-_,.*');
1545
 		$columns   = $this->parseGetParameter($get, 'columns', 'a-zA-Z0-9\-_,.*');
1549
-		$order     = $this->parseGetParameter($get, 'order', 'a-zA-Z0-9\-_,');
1546
+		$orderings = $this->parseGetParameterArray($get, 'order', 'a-zA-Z0-9\-_,');
1550
 		$transform = $this->parseGetParameter($get, 'transform', 't1');
1547
 		$transform = $this->parseGetParameter($get, 'transform', 't1');
1551
 
1548
 
1552
 		$tables    = $this->processTableAndIncludeParameters($database,$table,$include,$action);
1549
 		$tables    = $this->processTableAndIncludeParameters($database,$table,$include,$action);
1554
 		$satisfy   = $this->processSatisfyParameter($tables,$satisfy);
1551
 		$satisfy   = $this->processSatisfyParameter($tables,$satisfy);
1555
 		$filters   = $this->processFiltersParameter($tables,$satisfy,$filters);
1552
 		$filters   = $this->processFiltersParameter($tables,$satisfy,$filters);
1556
 		$page      = $this->processPageParameter($page);
1553
 		$page      = $this->processPageParameter($page);
1557
-		$order     = $this->processOrderParameter($order);
1554
+		$orderings = $this->processOrderingsParameter($orderings);
1558
 
1555
 
1559
 		// reflection
1556
 		// reflection
1560
 		list($tables,$collect,$select) = $this->findRelations($tables,$database,$auto_include);
1557
 		list($tables,$collect,$select) = $this->findRelations($tables,$database,$auto_include);
1586
 			}
1583
 			}
1587
 		}
1584
 		}
1588
 
1585
 
1589
-		return compact('action','database','tables','key','page','filters','fields','order','transform','multi','inputs','collect','select');
1586
+		return compact('action','database','tables','key','page','filters','fields','orderings','transform','multi','inputs','collect','select');
1590
 	}
1587
 	}
1591
 
1588
 
1592
 	protected function addWhereFromFilters($filters,&$sql,&$params) {
1589
 	protected function addWhereFromFilters($filters,&$sql,&$params) {
1615
 		}
1612
 		}
1616
 	}
1613
 	}
1617
 
1614
 
1615
+	protected function addOrderByFromOrderings($orderings,&$sql,&$params) {
1616
+		foreach ($orderings as $i=>$ordering) {
1617
+			$sql .= $i==0?' ORDER BY ':', ';
1618
+			$sql .= '! '.$ordering[1];
1619
+			$params[] = $ordering[0];
1620
+		}
1621
+	}
1622
+
1618
 	protected function listCommandInternal($parameters) {
1623
 	protected function listCommandInternal($parameters) {
1619
 		extract($parameters);
1624
 		extract($parameters);
1620
 		echo '{';
1625
 		echo '{';
1622
 		// first table
1627
 		// first table
1623
 		$count = false;
1628
 		$count = false;
1624
 		echo '"'.$table.'":{';
1629
 		echo '"'.$table.'":{';
1625
-		if (is_array($order) && is_array($page)) {
1630
+		if (is_array($orderings) && is_array($page)) {
1626
 			$params = array();
1631
 			$params = array();
1627
 			$sql = 'SELECT COUNT(*) FROM !';
1632
 			$sql = 'SELECT COUNT(*) FROM !';
1628
 			$params[] = $table;
1633
 			$params[] = $table;
1641
 		$sql .= ' FROM !';
1646
 		$sql .= ' FROM !';
1642
 		$params[] = $table;
1647
 		$params[] = $table;
1643
 		if (isset($filters[$table])) {
1648
 		if (isset($filters[$table])) {
1644
-				$this->addWhereFromFilters($filters[$table],$sql,$params);
1649
+			$this->addWhereFromFilters($filters[$table],$sql,$params);
1645
 		}
1650
 		}
1646
-		if (is_array($order)) {
1647
-			$sql .= ' ORDER BY ! '.$order[1];
1648
-			$params[] = $order[0];
1651
+		if (is_array($orderings)) {
1652
+			$this->addOrderByFromOrderings($orderings,$sql,$params);
1649
 		}
1653
 		}
1650
-		if (is_array($order) && is_array($page)) {
1654
+		if (is_array($orderings) && is_array($page)) {
1651
 			$sql = $this->db->addLimitToSql($sql,$page[1],$page[0]);
1655
 			$sql = $this->db->addLimitToSql($sql,$page[1],$page[0]);
1652
 		}
1656
 		}
1653
 		if ($result = $this->db->query($sql,$params)) {
1657
 		if ($result = $this->db->query($sql,$params)) {

+ 16
- 2
tests/tests.php View File

324
 	{
324
 	{
325
 		$test = new API($this);
325
 		$test = new API($this);
326
 		for ($i=1;$i<=10;$i++) {
326
 		for ($i=1;$i<=10;$i++) {
327
-		  $test->post('/posts','{"user_id":1,"category_id":1,"content":"#'.$i.'"}');
328
-		  $test->expect(4+$i);
327
+			$test->post('/posts','{"user_id":1,"category_id":1,"content":"#'.$i.'"}');
328
+			$test->expect(4+$i);
329
 		}
329
 		}
330
 		$test->get('/posts?page=2,2&order=id');
330
 		$test->get('/posts?page=2,2&order=id');
331
 		$test->expect('{"posts":{"columns":["id","user_id","category_id","content"],"records":[[5,1,1,"#1"],[6,1,1,"#2"]],"results":11}}');
331
 		$test->expect('{"posts":{"columns":["id","user_id","category_id","content"],"records":[[5,1,1,"#1"],[6,1,1,"#2"]],"results":11}}');
332
 	}
332
 	}
333
 
333
 
334
+	public function testListWithPaginateInMultipleOrder()
335
+	{
336
+		$test = new API($this);
337
+		$test->get('/posts?page=1,2&order[]=category_id,asc&order[]=id,desc');
338
+		$test->expect('{"posts":{"columns":["id","user_id","category_id","content"],"records":[[14,1,1,"#10"],[12,1,1,"#8"]],"results":11}}');
339
+	}
340
+
341
+	public function testListWithPaginateInDescendingOrder()
342
+	{
343
+		$test = new API($this);
344
+		$test->get('/posts?page=2,2&order=id,desc');
345
+		$test->expect('{"posts":{"columns":["id","user_id","category_id","content"],"records":[[11,1,1,"#7"],[10,1,1,"#6"]],"results":11}}');
346
+	}
347
+
334
 	public function testListWithPaginateLastPage()
348
 	public function testListWithPaginateLastPage()
335
 	{
349
 	{
336
 		$test = new API($this);
350
 		$test = new API($this);

Loading…
Cancel
Save