From 8f750d2b352e756991241ee98aa4fef832f32c89 Mon Sep 17 00:00:00 2001 From: Farshid Rezaei Date: Wed, 15 Oct 2025 23:50:02 +0330 Subject: [PATCH 1/2] feat: Add orderByWithPriority --- src/Illuminate/Database/Eloquent/Builder.php | 13 ++++++++ src/Illuminate/Database/Query/Builder.php | 25 +++++++++++++++ tests/Database/DatabaseQueryBuilderTest.php | 33 ++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index d32a17b207ef..7e2e23430ddd 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -439,6 +439,19 @@ public function latest($column = null) return $this; } + /** + * Order the query by a column with a given set of priority values. + * + * @param array{string|\BackedEnum}|null $priorities + * @return $this + */ + public function orderByWithPriority(string $column, ?array $priorities = [], ?string $direction = 'asc') + { + $this->query->orderByWithPriority(...func_get_args()); + + return $this; + } + /** * Add an "order by" clause for a timestamp to the query. * diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 03195c5b9f4f..6716dc4a1f8a 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -2704,6 +2704,31 @@ public function orderBy($column, $direction = 'asc') return $this; } + /** + * Order the query by a column with a given set of priority values. + * + * @param array{string|\BackedEnum}|null $priorities + * @return $this + */ + public function orderByWithPriority(string $column, ?array $priorities = [], ?string $direction = 'asc') + { + if (empty($priorities)) { + return $this->orderBy($column, $direction); + } + + // Convert enums to their backing values if needed + $priorities = array_map(function ($value) { + return $value instanceof \UnitEnum + ? ($value instanceof \BackedEnum ? $value->value : $value->name) + : $value; + }, $priorities); + + $bindings = array_map(fn () => '?', $priorities); + $sql = "FIELD({$this->grammar->wrap($column)}, ".implode(',', $bindings).')'; + + return $this->orderByRaw($sql.' '.$direction, $priorities); + } + /** * Add a descending "order by" clause to the query. * diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 53629cdff191..dc6973f14603 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -2077,6 +2077,39 @@ public function testOrderBys() $this->assertEquals([1, 1, 'news', 'opinion'], $builder->getBindings()); } + public function test_order_by_with_priority_generates_expected_sql() + { + $properties = [ + 'done', + 'pending', + ]; + + $builder = $this->getBuilder(); + $builder->select('*')->from('posts')->orderByWithPriority('status', $properties); + + $this->assertSame( + 'select * from "posts" order by FIELD("status", ?,?) asc', + $builder->toSql() + ); + + $this->assertEquals($properties, $builder->getBindings()); + + $properties = [ + StringStatus::done, + StringStatus::pending, + ]; + + $builder = $this->getBuilder(); + $builder->select('*')->from('posts')->orderByWithPriority('status', $properties); + + $this->assertSame( + 'select * from "posts" order by FIELD("status", ?,?) asc', + $builder->toSql() + ); + + $this->assertEquals(array_map(fn (StringStatus $item) => $item->value, $properties), $builder->getBindings()); + } + public function testLatest() { $builder = $this->getBuilder(); From 8debe89e819db86968ab81e82853c259a4a09934 Mon Sep 17 00:00:00 2001 From: Farshid Rezaei Date: Fri, 17 Oct 2025 12:48:32 +0330 Subject: [PATCH 2/2] feat: Add orderByWithPriority --- src/Illuminate/Database/Eloquent/Builder.php | 2 +- src/Illuminate/Database/Query/Builder.php | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index 7e2e23430ddd..f192f9587e27 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -442,7 +442,7 @@ public function latest($column = null) /** * Order the query by a column with a given set of priority values. * - * @param array{string|\BackedEnum}|null $priorities + * @param (string|\BackedEnum|\UnitEnum)[]|null $priorities * @return $this */ public function orderByWithPriority(string $column, ?array $priorities = [], ?string $direction = 'asc') diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index 6716dc4a1f8a..26bc023522c7 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -2707,7 +2707,7 @@ public function orderBy($column, $direction = 'asc') /** * Order the query by a column with a given set of priority values. * - * @param array{string|\BackedEnum}|null $priorities + * @param (string|\BackedEnum|\UnitEnum)[]|null $priorities * @return $this */ public function orderByWithPriority(string $column, ?array $priorities = [], ?string $direction = 'asc') @@ -2716,14 +2716,10 @@ public function orderByWithPriority(string $column, ?array $priorities = [], ?st return $this->orderBy($column, $direction); } - // Convert enums to their backing values if needed - $priorities = array_map(function ($value) { - return $value instanceof \UnitEnum - ? ($value instanceof \BackedEnum ? $value->value : $value->name) - : $value; - }, $priorities); + $priorities = array_map(enum_value(...), $priorities); $bindings = array_map(fn () => '?', $priorities); + $sql = "FIELD({$this->grammar->wrap($column)}, ".implode(',', $bindings).')'; return $this->orderByRaw($sql.' '.$direction, $priorities);