如何将含自定义排序字段的MySQL原生查询转为Laravel Eloquent?
解决Laravel原生SQL转Eloquent后无法调用关联的问题
你遇到的问题根源很明确:用DB::select()执行原生SQL返回的是标准PHP对象(StdClass),而不是你的CampaignInfluencer模型实例,自然没法调用模型里定义的user()关联方法。下面是把你的原生查询完全转换成Eloquent查询构建器的方案,这样返回的就是模型实例,关联关系就能正常使用了:
完整Eloquent实现代码
假设你的模型类是App\Models\CampaignInfluencer(根据你的实际命名空间调整):
use App\Models\CampaignInfluencer; $campaignInfluencers = CampaignInfluencer::select([ 'campaign_influencers.*', DB::raw("CASE influencer_status WHEN 'PENDING' THEN 3 WHEN 'ACTIVE' THEN 1 WHEN 'LIVE' THEN 2 WHEN 'ACCEPTED' THEN 0 ELSE 5 END AS order_field") ]) ->where('campaign_id', $id) ->orderBy('order_field') ->get();
或者更简洁的写法,用selectRaw直接拼接字段:
$campaignInfluencers = CampaignInfluencer::selectRaw(" campaign_influencers.*, CASE influencer_status WHEN 'PENDING' THEN 3 WHEN 'ACTIVE' THEN 1 WHEN 'LIVE' THEN 2 WHEN 'ACCEPTED' THEN 0 ELSE 5 END AS order_field ") ->where('campaign_id', $id) ->orderBy('order_field') ->get();
为什么这样能解决问题?
- 从
CampaignInfluencer模型出发调用查询构建器,最终get()方法返回的是Collection集合,里面的每个元素都是CampaignInfluencer模型实例。 - 模型实例会继承Eloquent的所有特性,包括你定义的
user()关联方法,所以现在你可以正常调用$campaignInfluencer->user了:
foreach ($campaignInfluencers as $campaignInfluencer) { $user = $campaignInfluencer->user; // 现在可以正常生效啦! }
额外优化建议
如果这个自定义排序逻辑经常用到,你可以把它封装成模型的一个本地作用域(Local Scope),让代码更复用:
在CampaignInfluencer模型里添加:
public function scopeOrderByStatus($query) { return $query->selectRaw(" *, CASE influencer_status WHEN 'PENDING' THEN 3 WHEN 'ACTIVE' THEN 1 WHEN 'LIVE' THEN 2 WHEN 'ACCEPTED' THEN 0 ELSE 5 END AS order_field ") ->orderBy('order_field'); }
之后查询就可以简化成:
$campaignInfluencers = CampaignInfluencer::where('campaign_id', $id) ->orderByStatus() ->get();
内容的提问来源于stack exchange,提问作者Cruze
相关产品推荐
相关产品推荐

