Skip to content

Conversation

@farshidrezaei
Copy link

@farshidrezaei farshidrezaei commented Oct 15, 2025

This PR introduces a new orderByWithPriority method for the query builder, allowing developers to sort results by a defined list of prioritized values — complementing existing methods like orderBy, orderByRaw, and orderByDesc.

Problem

While Eloquent provides expressive methods for sorting columns (orderBy, orderByDesc, etc.), it currently lacks a concise way to order results based on custom priority lists.

For example, suppose we want to list users so that admins appear first, followed by managers, then regular users. Today, this requires verbose SQL or raw expressions:

User::orderByRaw("FIELD(role, 'admin', 'manager', 'user')")->get();

This approach is less readable, harder to maintain, and inconsistent with Laravel’s fluent query syntax.

Solution

The new orderByWithPriority method provides a clean, expressive way to handle this use case:

User::orderByWithPriority('role', ['admin', 'manager', 'user'])->get();

This generates the equivalent SQL:

ORDER  BY FIELD(`role`, 'admin', 'manager', 'user')

You can also combine it with other orderings:

User::orderByWithPriority('role', ['admin', 'manager'])
    ->orderBy('created_at', 'desc')
    ->get();

Enum Support

The method supports PHP enums natively — it will automatically extract backing values:

enum  Role: string { 
      case Admin = 'admin'; 
      case Manager = 'manager'; 
      case User = 'user';
}

 User::orderByWithPriority('role', [Role::Admin, Role::Manager, Role::User])->get();

This yields the same output, ensuring a seamless experience when using modern enum-backed domain models.

Before / After

Before

User::orderByRaw("FIELD(role, 'admin', 'manager', 'user')")->get();

After

User::orderByWithPriority('role', ['admin', 'manager', 'user'])->get();

Behavior Matrix

Input Type Example Behavior
Array of strings ['high', 'medium', 'low'] Orders by FIELD(column, ...)
Array of enums [Status::Active, Status::Pending] Orders by enum values
Empty array [] Falls back to regular orderBy(column)
Mixed types ['admin', Role::User] All values normalized before binding

Naming

I considered alternatives like orderByField, orderByValues, and orderByPriority, but settled on orderByWithPriority for its clarity and alignment with Laravel’s naming conventions (whereIn, withCount, withSum, etc.).

It communicates both intent and flexibility — “order by this column, with this specific priority.”

Example Use Cases

  • Prioritize featured items:
Product::orderByWithPriority('status', ['featured', 'popular', 'standard'])->get();
  • Sort tickets by severity:
Ticket::orderByWithPriority('severity', ['critical', 'high', 'medium', 'low'])->get();
  • Display enum-based roles or states in meaningful order.

Implementation Summary

Internally, the method wraps the column name with the query grammar and uses orderByRaw with positional bindings to ensure safety and consistency. It automatically normalizes enums to their backing values.

/**
     * Order the query by a column with a given set of priority values.
     *
     * @param  (string|\BackedEnum|\UnitEnum)[]|null  $priorities
     * @return $this
     */
    public function orderByWithPriority(string $column, ?array $priorities = [], ?string $direction = 'asc')
    {
        if (empty($priorities)) {
            return $this->orderBy($column, $direction);
        }

        $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);
    }

Tests

Added tests in DatabaseQueryBuilderTest to ensure:

  • Correct SQL and bindings are generated

  • Empty priorities gracefully fall back to standard ordering

  • Enum-backed priorities resolve correctly

Summary

  • Adds a fluent, expressive method for priority-based sorting

  • Reduces reliance on raw SQL

  • Supports modern PHP enums

  • Aligns perfectly with Laravel’s elegant query syntax

Copy link
Contributor

@shaedrich shaedrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be interesting to have FIELD as native part of the query grammar in the future for other use cases 🤔

Copy link
Contributor

@shaedrich shaedrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I'm not a maintainer, I can neither accept nor reject your PR, but Taylor can and will

Anyway, LGTM now 👍🏻

@taylorotwell
Copy link
Member

Thanks for your pull request to Laravel!

Unfortunately, I'm going to delay merging this code for now. To preserve our ability to adequately maintain the framework, we need to be very careful regarding the amount of code we include.

If applicable, please consider releasing your code as a package so that the community can still take advantage of your contributions!

@farshidrezaei
Copy link
Author

💔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants