Laravel 8 Eloquent如何查询符合总热量限制的随机分类食谱组合
Laravel 8 Eloquent实现符合热量上限的随机餐食组合
假设你的食谱数据对应Recipe模型(对应数据库表recipes,字段包括name、category、calories),可以通过以下两种方案实现需求:
方案一:PHP层生成并筛选组合(适合小数据量)
这种方式逻辑直观,适合每个分类下食谱数量不多的场景:
namespace App\Http\Controllers; use App\Models\Recipe; use Illuminate\Http\Request; class MealPlanController extends Controller { public function getRandomDailyMeal(int $calorieLimit = 1500) { // 获取各分类的食谱集合 $snacks = Recipe::where('category', '零食')->get(); $lunches = Recipe::where('category', '午餐')->get(); $dinners = Recipe::where('category', '晚餐')->get(); $validCombos = []; // 遍历所有可能的三餐组合,筛选热量达标的 foreach ($snacks as $snack) { foreach ($lunches as $lunch) { foreach ($dinners as $dinner) { $total = $snack->calories + $lunch->calories + $dinner->calories; if ($total <= $calorieLimit) { $validCombos[] = [ '零食' => $snack, '午餐' => $lunch, '晚餐' => $dinner, '总热量' => $total ]; } } } } // 无符合条件的组合时返回null,可根据业务调整 if (empty($validCombos)) { return null; } // 随机返回一个有效组合 return $validCombos[array_rand($validCombos)]; } }
方案二:数据库层直接查询筛选(适合大数据量)
通过数据库联表查询直接生成符合条件的组合,性能更优,尤其当食谱数量较多时:
namespace App\Http\Controllers; use App\Models\Recipe; use Illuminate\Support\Facades\DB; use Illuminate\Http\Request; class MealPlanController extends Controller { public function getRandomDailyMealFromDb(int $calorieLimit = 1500) { $validCombo = Recipe::select( 's.name as 零食名称', 's.calories as 零食热量', 'l.name as 午餐名称', 'l.calories as 午餐热量', 'd.name as 晚餐名称', 'd.calories as 晚餐热量', DB::raw('s.calories + l.calories + d.calories as 总热量') ) ->from('recipes as s') ->where('s.category', '=', '零食') ->crossJoin('recipes as l') ->where('l.category', '=', '午餐') ->crossJoin('recipes as d') ->where('d.category', '=', '晚餐') ->whereRaw('s.calories + l.calories + d.calories <= ?', [$calorieLimit]) ->inRandomOrder() ->first(); return $validCombo; } }
注意事项
- 确保数据库中
category字段的值与查询条件完全匹配(避免空格、大小写不一致等问题) - 若业务中分类可能新增,可将分类列表抽成配置数组,动态生成查询或循环逻辑,避免硬编码
- 当无符合热量上限的组合时,需根据业务需求添加 fallback 逻辑(比如返回热量最接近上限的组合,或提示用户调整上限)
内容的提问来源于stack exchange,提问作者Rubyx
相关产品推荐
相关产品推荐

