Laravel eloquent how to order collection by accessor in appends array

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Laravel Eloquent: How to Order Collections by Accessor in Appends Array

As developers working with Eloquent, we often deal with scenarios where our application logic, encapsulated within model accessors, seems intuitive. We define methods like lastDateAttribute to provide convenient, computed data to the view layer. However, when we try to use these accessor results directly in collection sorting or filtering, we often run into unexpected roadblocks.

This post dives into a common pain point: attempting to order an Eloquent collection using a custom accessor that relies on complex database relationships (like many-to-many joins). We will explore why simple ordering fails and demonstrate the robust, performant ways to achieve your desired sorting outcome by leveraging raw SQL within Eloquent.

The Problem with Sorting Accessors Directly

You’ve encountered a classic issue: attempting to sort using an accessor that computes data dynamically across related tables does not work as expected.

Consider your model structure where you have an accessor:

// In Song Model
public function getLastDateAttribute()
{
    // This method relies on accessing the 'events' relationship
    if (!$this->events) return null;
    return $this->events[0]->date->formatLocalized('%d.%m.%Y (%a, %Hч)');
}

When you execute $songs->orderBy('lastDate', 'desc');, Eloquent attempts to find a column named last_date in the mg_songs table. Since lastDate is an accessor defined in PHP and not a direct database column, this operation fails because there is no corresponding column to sort by at the database level.

The accessor is purely for presentation; it doesn't translate into an actual, indexable column in your underlying relational structure.

The Solution: Sorting via Database Expressions

To correctly order your collection based on a computed value derived from joins and aggregations, you must delegate the sorting logic back to the database itself. This means using Eloquent’s ability to inject raw SQL expressions into the orderBy clause.

The most efficient way to solve this is by utilizing correlated subqueries or grouping operations directly within the query builder, similar to the complex SQL-request you provided: finding the maximum date associated with each song.

Implementing Complex Ordering with orderByRaw

Since your requirement involves calculating a specific value (the maximum event date for each song) before sorting, we need to use DB::raw() within the orderBy method. This allows us to execute the exact SQL logic you designed directly against the database.

Here is how you would modify your query to sort by the calculated date:

use Illuminate\Support\Facades\DB;

// Assuming $songs is your Eloquent collection
$songs = Song::query()
    // Use orderByRaw to instruct the database exactly how to calculate the sorting key
    ->orderBy(DB::raw('(SELECT MAX(e.date) FROM events e JOIN song_event se ON (e.id = se.event_id) WHERE se.song_id = mg_songs.song_id) DESC'))
    ->by('some_other_field', 'asc') // You can still order by standard columns as well
    ->get();

Explanation of the approach:

  1. DB::raw(...): This wrapper tells Eloquent to treat the enclosed string as raw SQL that should be executed in the ORDER BY clause.
  2. Correlated Subquery: The expression inside DB::raw() is a correlated subquery. For every row being processed in the main mg_songs table (aliased as s), the database executes the inner query to find the maximum date (MAX(e.date)) from the related tables (events, song_event).
  3. Performance: By performing this calculation within the ORDER BY clause, the database handles the heavy lifting efficiently, avoiding loading all results into PHP only to sort them manually. This is significantly faster and more scalable than fetching everything and sorting in PHP memory.

Best Practices for Eloquent Data Retrieval

When dealing with complex data retrieval, remember that Eloquent shines when it acts as an elegant wrapper around powerful database operations. While accessors are great for presentation, use raw expressions like DB::raw() or Eloquent Scopes to handle complex filtering and ordering logic on the backend. This keeps your business logic correctly situated where it belongs—in the relational database. For more advanced querying techniques, exploring features provided by frameworks like Laravel is highly recommended.

Conclusion

In summary, you cannot directly order an Eloquent collection by a simple accessor if that accessor relies on calculated relationships and joins. The solution is to shift the sorting responsibility from PHP application logic to the SQL query itself. By using orderBy(DB::raw(...)), you gain the power to execute complex, optimized database queries directly against your data, ensuring both correctness and superior performance.