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,6 +224,7 @@ With the "order" parameter you can sort. By default the sort is in ascending ord
224 224
 
225 225
 ```
226 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 230
 Output:
@@ -232,6 +233,8 @@ Output:
232 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 238
 ### List + Order + Pagination
236 239
 
237 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,14 +187,6 @@ class MySQL implements DatabaseInterface {
187 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 190
 	public function likeEscape($string) {
199 191
 		return addcslashes($string,'%_');
200 192
 	}
@@ -1126,13 +1118,18 @@ class PHP_CRUD_API {
1126 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 1135
 	protected function convertFilter($field, $comparator, $value) {
@@ -1546,7 +1543,7 @@ class PHP_CRUD_API {
1546 1543
 		$filters   = $this->parseGetParameterArray($get, 'filter', false);
1547 1544
 		$satisfy   = $this->parseGetParameter($get, 'satisfy', 'a-zA-Z0-9\-_,.');
1548 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 1547
 		$transform = $this->parseGetParameter($get, 'transform', 't1');
1551 1548
 
1552 1549
 		$tables    = $this->processTableAndIncludeParameters($database,$table,$include,$action);
@@ -1554,7 +1551,7 @@ class PHP_CRUD_API {
1554 1551
 		$satisfy   = $this->processSatisfyParameter($tables,$satisfy);
1555 1552
 		$filters   = $this->processFiltersParameter($tables,$satisfy,$filters);
1556 1553
 		$page      = $this->processPageParameter($page);
1557
-		$order     = $this->processOrderParameter($order);
1554
+		$orderings = $this->processOrderingsParameter($orderings);
1558 1555
 
1559 1556
 		// reflection
1560 1557
 		list($tables,$collect,$select) = $this->findRelations($tables,$database,$auto_include);
@@ -1586,7 +1583,7 @@ class PHP_CRUD_API {
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 1589
 	protected function addWhereFromFilters($filters,&$sql,&$params) {
@@ -1615,6 +1612,14 @@ class PHP_CRUD_API {
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 1623
 	protected function listCommandInternal($parameters) {
1619 1624
 		extract($parameters);
1620 1625
 		echo '{';
@@ -1622,7 +1627,7 @@ class PHP_CRUD_API {
1622 1627
 		// first table
1623 1628
 		$count = false;
1624 1629
 		echo '"'.$table.'":{';
1625
-		if (is_array($order) && is_array($page)) {
1630
+		if (is_array($orderings) && is_array($page)) {
1626 1631
 			$params = array();
1627 1632
 			$sql = 'SELECT COUNT(*) FROM !';
1628 1633
 			$params[] = $table;
@@ -1641,13 +1646,12 @@ class PHP_CRUD_API {
1641 1646
 		$sql .= ' FROM !';
1642 1647
 		$params[] = $table;
1643 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 1655
 			$sql = $this->db->addLimitToSql($sql,$page[1],$page[0]);
1652 1656
 		}
1653 1657
 		if ($result = $this->db->query($sql,$params)) {

+ 16
- 2
tests/tests.php View File

@@ -324,13 +324,27 @@ class PHP_CRUD_API_Test extends PHPUnit_Framework_TestCase
324 324
 	{
325 325
 		$test = new API($this);
326 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 330
 		$test->get('/posts?page=2,2&order=id');
331 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 348
 	public function testListWithPaginateLastPage()
335 349
 	{
336 350
 		$test = new API($this);

Loading…
Cancel
Save