Laravel中重写last()方法?解决关联查询最新记录不一致问题
Laravel一对多关联中按ID而非created_at获取最新余额记录
现有关联代码与问题
我在User和UserBalances模型间建立了一对多关联:
User模型代码
public function user_balances(){ return $this->hasMany(UserBalances::class); }
UserBalances模型代码(注意:此处存在笔误,已修正)
原代码中belongsTo关联的模型写错了,正确写法应为:
public function user(){ return $this->belongsTo(User::class); }
当前获取方式与问题
我之前通过以下方式获取用户的最后一条余额记录:
$user = User::first(); $user->user_balances->last()
但由于余额记录生成速度快,多条记录可能出现相同的created_at时间戳,导致last()方法(依赖集合默认排序)无法稳定获取到真正最新的记录(ID最大的那条)。
我也尝试过直接查询的方式:
$user = User::first(); $user_balance_last = UserBalance::where('user_id', $user->id)->latest('id')->first();
解决方案
1. 新增专属关联获取最新记录(推荐)
在User模型中新增一个hasOne关联,利用Laravel的latestOfMany方法直接关联到最新的余额记录,指定按id排序:
public function latest_user_balance(){ return $this->hasOne(UserBalances::class)->latestOfMany('id'); }
使用时直接调用关联即可,无需额外处理:
$user = User::first(); $latestBalance = $user->latest_user_balance;
这种方式是Laravel官方推荐的,仅查询单条记录,性能最优且结果稳定。
2. 修改原有关联的默认排序
如果需要保留原有的user_balances关联集合,可在关联中设置默认按id升序排序,这样last()就能拿到ID最大的记录:
public function user_balances(){ return $this->hasMany(UserBalances::class)->orderBy('id', 'asc'); }
使用方式不变:
$user = User::first(); $latestBalance = $user->user_balances->last();
注意:此方式会加载该用户的所有余额记录,数据量大时性能较差。
3. 优化直接查询的写法
你之前尝试的直接查询可以优化为关联查询,无需手动拼接user_id条件:
$user = User::first(); $latestBalance = $user->user_balances()->latest('id')->first();
这种写法更符合Laravel关联查询的规范,同时保证只查询单条最新记录。
内容的提问来源于stack exchange,提问作者randy-ar
相关产品推荐
相关产品推荐

