diff --git a/src/Query/SelectQuery.php b/src/Query/SelectQuery.php index b698db7..4644d3e 100644 --- a/src/Query/SelectQuery.php +++ b/src/Query/SelectQuery.php @@ -52,7 +52,7 @@ class SelectQuery extends ActiveQuery implements /** @var array */ protected $columns = ['*']; - /** @var array */ + /** @var string[][]|FragmentInterface[][] */ protected $orderBy = []; /** @var array */ @@ -165,18 +165,32 @@ public function forUpdate(): SelectQuery public function orderBy($expression, $direction = self::SORT_ASC): SelectQuery { if (!is_array($expression)) { - $this->orderBy[] = [$expression, $direction]; - + $this->addOrder($expression, $direction); return $this; } foreach ($expression as $nested => $dir) { - $this->orderBy[] = [$nested, $dir]; + $this->addOrder($nested, $dir); } return $this; } + /** + * @param string|FragmentInterface $field + * @param string $order Sorting direction, ASC|DESC. + * @return self|$this + */ + private function addOrder($field, string $order): SelectQuery + { + if (!is_string($field)) { + $this->orderBy[] = [$field, $order]; + } elseif (!array_key_exists($field, $this->orderBy)) { + $this->orderBy[$field] = [$field, $order]; + } + return $this; + } + /** * Column or expression to group query by. * @@ -420,7 +434,7 @@ public function getTokens(): array 'where' => $this->whereTokens, 'having' => $this->havingTokens, 'groupBy' => $this->groupBy, - 'orderBy' => $this->orderBy, + 'orderBy' => array_values($this->orderBy), 'limit' => $this->limit, 'offset' => $this->offset, 'union' => $this->unionTokens, diff --git a/tests/Database/SelectQueryTest.php b/tests/Database/SelectQueryTest.php index c2478e5..a9df70b 100644 --- a/tests/Database/SelectQueryTest.php +++ b/tests/Database/SelectQueryTest.php @@ -815,6 +815,36 @@ public function testOrderByDesc3(): void ); } + public function testOrderByTwiceBySameName(): void + { + $select = $this->database + ->select() + ->from(['users']) + ->where(['name' => 'Anton']) + ->orderBy('name', 'DESC') + ->orderBy('name', 'ASC'); + + $this->assertSameQuery( + 'SELECT * FROM {users} WHERE {name} = ? ORDER BY {name} DESC', + $select + ); + } + + public function testOrderByTwiceBySameNameArray(): void + { + $select = $this->database + ->select() + ->from(['users']) + ->where(['name' => 'Anton']) + ->orderBy('name', 'DESC') + ->orderBy(['name' => 'ASC', 'foo' => 'DESC']); + + $this->assertSameQuery( + 'SELECT * FROM {users} WHERE {name} = ? ORDER BY {name} DESC, {foo} DESC', + $select + ); + } + public function testMultipleOrderBy(): void { $select = $this->database