Skip to content

Commit 620d6ab

Browse files
authored
Fix compiling queries that use orderByRaw with expressions (#57228)
* Fix compiling queries that use orderByRaw with expressions This fixes an issue caused by the removal of automatic casting of Expression objects to strings in Laravel 10. $sql = DB::table('users') ->select('id') ->orderByRaw(DB::raw('length(name) desc')) ->toSql(); fails without this change. * Update src/Illuminate/Database/Query/Grammars/Grammar.php * Add tests for compileOrders method in Grammar
1 parent 214005f commit 620d6ab

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

src/Illuminate/Database/Query/Grammars/Grammar.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,11 @@ protected function compileOrders(Builder $query, $orders)
987987
*/
988988
protected function compileOrdersToArray(Builder $query, $orders)
989989
{
990-
return array_map(function ($order) {
990+
return array_map(function ($order) use ($query) {
991+
if (isset($order['sql']) && $order['sql'] instanceof Expression) {
992+
return $order['sql']->getValue($query->getGrammar());
993+
}
994+
991995
return $order['sql'] ?? $this->wrap($order['column']).' '.$order['direction'];
992996
}, $orders);
993997
}

tests/Database/DatabaseQueryGrammarTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,40 @@ public function testWhereRawReturnsStringWhenStringPassed()
4242

4343
$this->assertSame('select * from "users"', $rawQuery);
4444
}
45+
46+
public function testCompileOrdersAcceptsExpression()
47+
{
48+
$builder = m::mock(Builder::class);
49+
$grammar = new Grammar(m::mock(Connection::class));
50+
51+
// compileOrders() calls $query->getGrammar() → return our $grammar
52+
$builder->shouldReceive('getGrammar')->andReturn($grammar);
53+
54+
$orders = [
55+
['sql' => new Expression('length("name") desc')], // mimics orderByRaw(DB::raw(...))
56+
];
57+
58+
$ref = new \ReflectionClass($grammar);
59+
$method = $ref->getMethod('compileOrders'); // protected
60+
$sql = $method->invoke($grammar, $builder, $orders);
61+
62+
$this->assertSame('order by length("name") desc', strtolower($sql));
63+
}
64+
65+
public function testCompileOrdersAcceptsExpressionWithPlaceholders()
66+
{
67+
$builder = m::mock(Builder::class);
68+
$grammar = new Grammar(m::mock(Connection::class));
69+
$builder->shouldReceive('getGrammar')->andReturn($grammar);
70+
71+
$orders = [
72+
['sql' => new Expression('field(status, ?, ?) asc')],
73+
];
74+
75+
$ref = new \ReflectionClass($grammar);
76+
$method = $ref->getMethod('compileOrders');
77+
$sql = $method->invoke($grammar, $builder, $orders);
78+
79+
$this->assertSame('order by field(status, ?, ?) asc', strtolower($sql));
80+
}
4581
}

0 commit comments

Comments
 (0)