Support type Closure|Expression|ModelBuilder|static|string of $column for QueryBuilder::orderBy(). (#6868)

Co-authored-by: 李铭昕 <715557344@qq.com>
This commit is contained in:
@长久同学 2024-06-14 13:20:46 +08:00 committed by GitHub
parent c7ff73ad0d
commit 7c128957a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 42 additions and 6 deletions

View File

@ -10,6 +10,7 @@
## Optimized ## Optimized
- [#6870](https://github.com/hyperf/hyperf/pull/6870) Updated default path for factories in Model Factory construct method. - [#6870](https://github.com/hyperf/hyperf/pull/6870) Updated default path for factories in Model Factory construct method.
- [#6868](https://github.com/hyperf/hyperf/pull/6868) Support type `Closure|Expression|ModelBuilder|static|string` of `$column` for `QueryBuilder::orderBy()`.
# v3.1.26 - 2024-06-13 # v3.1.26 - 2024-06-13

View File

@ -1806,12 +1806,19 @@ class Builder
/** /**
* Add an "order by" clause to the query. * Add an "order by" clause to the query.
* *
* @param string $column * @param Closure|Expression|ModelBuilder|static|string $column
* @param string $direction
* @return $this * @return $this
*/ */
public function orderBy($column, $direction = 'asc') public function orderBy(mixed $column, string $direction = 'asc'): static
{ {
if ($this->isQueryable($column)) {
[$query, $bindings] = $this->createSub($column);
$column = new Expression('(' . $query . ')');
$this->addBinding($bindings, $this->unions ? 'unionOrder' : 'order');
}
$this->{$this->unions ? 'unionOrders' : 'orders'}[] = [ $this->{$this->unions ? 'unionOrders' : 'orders'}[] = [
'column' => $column, 'column' => $column,
'direction' => strtolower($direction) === 'asc' ? 'asc' : 'desc', 'direction' => strtolower($direction) === 'asc' ? 'asc' : 'desc',

View File

@ -996,9 +996,7 @@ class Grammar extends BaseGrammar
protected function compileOrdersToArray(Builder $query, $orders): array protected function compileOrdersToArray(Builder $query, $orders): array
{ {
return array_map(function ($order) { return array_map(function ($order) {
return ! isset($order['sql']) return $order['sql'] ?? $this->wrap($order['column']) . ' ' . $order['direction'];
? $this->wrap($order['column']) . ' ' . $order['direction']
: $order['sql'];
}, $orders); }, $orders);
} }

View File

@ -13,9 +13,12 @@ declare(strict_types=1);
namespace HyperfTest\Database; namespace HyperfTest\Database;
use Hyperf\Database\MySqlConnection; use Hyperf\Database\MySqlConnection;
use Hyperf\Database\Query\Builder;
use Hyperf\Database\Query\Grammars\MySqlGrammar as MySqlQueryGrammar; use Hyperf\Database\Query\Grammars\MySqlGrammar as MySqlQueryGrammar;
use Hyperf\Database\Schema\Grammars\MySqlGrammar; use Hyperf\Database\Schema\Grammars\MySqlGrammar;
use Hyperf\Support\Fluent; use Hyperf\Support\Fluent;
use Hyperf\Support\Reflection\ClassInvoker;
use Mockery;
use PHPUnit\Framework\Attributes\CoversNothing; use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -39,4 +42,22 @@ class GrammarTest extends TestCase
$grammar = $conn->getQueryGrammar(); $grammar = $conn->getQueryGrammar();
$this->assertInstanceOf(MySqlQueryGrammar::class, $grammar); $this->assertInstanceOf(MySqlQueryGrammar::class, $grammar);
} }
public function testCompileOrdersToArray()
{
$grammar = new MySqlQueryGrammar();
/** @var MySqlQueryGrammar $grammar */
$grammar = new ClassInvoker($grammar);
$res = $grammar->compileOrdersToArray(Mockery::mock(Builder::class), [
[
'column' => 'id',
'direction' => 'asc',
],
[
'sql' => 'name desc',
],
]);
$this->assertSame(['`id` asc', 'name desc'], $res);
}
} }

View File

@ -172,6 +172,15 @@ class ModelRealBuilderTest extends TestCase
} }
} }
public function testOrderByModelBuilder()
{
$this->getContainer();
$sql = User::query()->orderBy(User::query()->select('id')->limit(1))->toSql();
$this->assertSame('select * from `user` order by (select `id` from `user` limit 1) asc', $sql);
}
public function testForPageAfterId() public function testForPageAfterId()
{ {
$this->getContainer(); $this->getContainer();