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

Laravel5.4+MySQL5.7:订单与司机技能及标签匹配查询问题

解决Laravel中司机技能与客户订单的匹配查询问题

看起来你在实现司机技能和订单匹配的逻辑时踩了几个常见的坑,我来帮你梳理并修复这些问题:

原代码的核心问题

  1. 错误引用固定技能项:循环里一直用$skills[0],导致永远只处理司机的第一个技能,完全忽略了其他技能
  2. 标签匹配逻辑错误:whereIn('tags', $tags_values)无法正确匹配多值的tags字段(不管是JSON数组还是逗号分隔字符串)
  3. 查询条件结构混乱:循环中的where会不断覆盖之前的条件,没有用分组逻辑实现"或"关系(司机匹配任意一个技能+标签组合即可)
  4. 冗余写法:where('type','=',NULL)可以简化为更规范的whereNull('type')

修复后的完整代码

// 先整理司机的技能及对应标签,方便后续查询使用
$driverSkills = UsersSkills::with('tags')
    ->where('user_id', $biker_id)
    ->get()
    ->map(function ($skill) {
        return [
            'skill_id' => $skill->skill_id,
            'tags' => $skill->tags->pluck('tag')->toArray()
        ];
    });

// 查询符合条件的订单
$orders = Order::whereHas('order_items', function ($query) use ($driverSkills) {
    // 所有技能匹配条件是"或"关系:司机只要匹配任意一个技能+标签组合即可
    $query->where(function ($subQuery) use ($driverSkills) {
        foreach ($driverSkills as $skill) {
            $subQuery->orWhere(function ($skillQuery) use ($skill) {
                // 匹配技能层级:订单项item_id以司机的skill_id开头(支持多层级匹配)
                $skillQuery->where('item_id', 'LIKE', $skill['skill_id'] . '%');
                
                // 匹配标签:如果该技能有标签,需要订单项包含所有标签(可根据需求调整为"任意匹配")
                if (!empty($skill['tags'])) {
                    foreach ($skill['tags'] as $tag) {
                        // 假设tags字段是MySQL JSON数组类型,用whereJsonContains匹配
                        $skillQuery->whereJsonContains('tags', $tag);
                        
                        // 如果tags是逗号分隔字符串,替换为下面的写法:
                        // $skillQuery->whereRaw('FIND_IN_SET(?, tags)', [$tag]);
                    }
                }
            });
        }
    });
})->where(function($query) use($maxLat,$minLat,$maxLon,$minLon,$biker_search_time,$estimation_id) {
    $query->where('done_by_expert', 1)
          ->whereBetween('destination_longitude', [$minLon, $maxLon])
          ->whereBetween('destination_latitude', [$minLat, $maxLat])
          ->where('status', 'pending')
          ->whereNull('type')
          ->where('vehicle_type_id', $estimation_id)
          ->whereNull('favorites')
          ->where('created_at', '>=', Carbon::now()->subMinute($biker_search_time));
})->get();

关键调整说明

  1. 技能数据预处理:用map把司机的技能和标签整理成结构化数组,避免在查询闭包里重复调用关系方法
  2. 分组查询逻辑:用嵌套的where+orWhere实现"多技能任意匹配"的逻辑,每个技能的匹配条件是独立的分组
  3. 标签匹配适配:
    • 如果你的tags字段是MySQL JSON数组类型:用whereJsonContains精准匹配标签
    • 如果是逗号分隔的字符串:用FIND_IN_SET函数进行匹配
  4. 灵活的标签逻辑:如果需求是"订单项只要有一个标签匹配即可",可以把标签循环改成:
    if (!empty($skill['tags'])) {
        $skillQuery->where(function ($tagQuery) use ($skill) {
            foreach ($skill['tags'] as $tag) {
                $tagQuery->orWhereJsonContains('tags', $tag);
            }
        });
    }
    

内容的提问来源于stack exchange,提问作者bitcodr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:11:36