Eloquent sortBy()无法按Accessor属性排序问题求助
Hey, let's get your driver sorting working properly. The main problem here is a misdefined Accessor method, which is causing sortBy('last_free_time') to fail. Here's how to fix it step by step:
1. Correct the Accessor in User Model
Laravel Accessors don't take custom parameters like $driver_id—they're tied directly to the current model instance. You should use $this->id to reference the current user's ID instead. Update your User.php:
// User.php public function getLastFreeTimeAttribute() { // Use $this->id to get the current user's ID return UserController::lastFreeTime($this->id); }
2. Ensure the Sorted Collection Has Proper Indexes
When you use sortBy(), Laravel preserves the original collection keys. This can sometimes cause unexpected behavior in loops. Reset the indexes with ->values() to guarantee your loop iterates in the correct sorted order:
// HomeController.php public function dashboard() { $drivers = User::whereHas('roles', function($q){ $q->where('slug', 'driver'); })->get(); // Add ->values() to reset indexes after sorting $sorteddrivers = $drivers->sortBy('last_free_time')->values(); $rides = Ride::all(); return view('dashboard')->with('rides', $rides)->with('drivers', $sorteddrivers); }
3. Clean Up Your View (Optional but Recommended)
Now that the Accessor is fixed, you can use the model attribute directly in your blade template instead of calling the controller static method—this is more aligned with Laravel's best practices:
<!-- dashboard.blade.php --> <tbody> @foreach($drivers as $driver) <tr> <td>{{ $driver->name }}</td> <!-- Use the Accessor attribute instead of direct controller call --> <td>{{ $driver->last_free_time }}</td> <td> @if( \App\Http\Controllers\UserController::isDriving($driver->id) ) <span class="bg-danger text-white p-1"><i class="fa fas fa-car fa-lg"></i> Busy</span> @else <span class="bg-success text-white p-1"><i class="fa fas fa-car fa-lg"></i> Free</span> @endif </td> </tr> @endforeach </tbody>
Why Your Original Code Failed
Your Accessor was expecting a $driver_id parameter, but Laravel automatically passes the raw value of the attribute (which doesn't exist in your database, so it's null) when calling the Accessor. This meant lastFreeTime(null) returned an empty string for every driver—so all values were identical, and sortBy() had nothing to sort on.
Bonus: Simplify the lastFreeTime Query
Since you likely have a relationship between User and Ride, you can simplify the query in UserController without using a raw join:
// UserController.php public static function lastFreeTime($driver_id) { $ride = Ride::where('user_id', $driver_id) ->orderBy('arrival', 'asc') ->first(); return $ride ? \Carbon\Carbon::parse($ride->arrival)->format('H:i') : ""; }
That should get your sorted drivers displaying correctly in the dashboard!
内容的提问来源于stack exchange,提问作者Marcelo Zárate

