You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Eloquent sortBy()无法按Accessor属性排序问题求助

Fixing Laravel Collection SortBy with Accessor Issue

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

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:31:33