Laravel Collection返回空数组求助:无法正确返回用户订单总价
Laravel 返回用户订单统计数据为空集合的问题解决
你好,我看到你在Laravel中处理用户订单总价统计时遇到了返回结果为空的问题——虽然dd($data)能看到属性,但实际返回的是空数组。下面帮你梳理问题根源和具体解决方案:
你的需求
遍历包含2个用户名的数组,通过用户名查询用户ID,统计每个用户在指定时间范围内的所有订单总价,最终返回每个用户的{'username': 用户名, 'totalPrice': 总价}格式数据。
当前问题核心
你直接给Collection对象添加了username和price属性,但Laravel在返回Collection时,只会序列化其内部的$items数组,你额外添加的对象属性不会被包含在返回结果里,这就是为什么return $data只返回[],但dd($data)能看到属性的原因。
问题分析与解决方案
以下是针对代码的具体修改建议,分点说明优化方向:
1. 修正Collection的使用方式
应该把每个用户的统计结果作为独立元素添加到集合中,而不是给集合本身添加属性;同时要确保每次循环用户时重置总价,避免跨用户累加错误。
2. 优化用户ID查询逻辑
避免使用原生SQL拼接(存在SQL注入风险),改用Eloquent查询更安全且符合Laravel的开发规范。
3. 优化模型中的统计逻辑
直接使用Laravel的sum()方法计算总价,不用查询所有订单再手动遍历求和,既能提升效率又能减少内存消耗。
修改后的完整代码
模型代码(优化求和逻辑)
use Carbon\Carbon; use Illuminate\Support\Facades\DB; use App\Models\Order; public static function getOrdersUserTotal($startDate, $endDate, $userId) { return Order::whereBetween('created_at', [Carbon::parse($startDate), Carbon::parse($endDate)]) ->where('user_id', $userId) // 过滤非报价订单 ->where(function ($query) { $query->where('is_quotation', 0)->orWhereNull('is_quotation'); }) // 确保订单未被软删除 ->whereNull('deleted_at') ->join('order_articles', 'orders.id', '=', 'order_articles.order_id') // 确保订单项未被软删除 ->whereNull('order_articles.deleted_at') ->join('order_article_configurations', 'order_articles.id', '=', 'order_article_configurations.order_article_id') // 确保订单配置项未被软删除 ->whereNull('order_article_configurations.deleted_at') // 计算单条订单总价并求和 ->sum(DB::raw('COALESCE(NULLIF(order_article_configurations.special_price, 0), order_article_configurations.price) * order_article_configurations.quantity')); }
控制器代码(修正集合使用与业务逻辑)
use Carbon\Carbon; use App\Models\User; use App\Models\Dashboard; use Illuminate\Http\Request; public static function getOrdersUser(Request $request = null) { // 处理日期参数 if ($request) { $startDate = $request->input('start_date'); $endDate = $request->input('end_date'); } else { $startDate = Carbon::now()->subDays(30); $endDate = Carbon::now(); } $users = ['merijn', 'stefan']; // 初始化空集合 $data = collect(); foreach ($users as $user) { // 用Eloquent查询用户ID,避免SQL注入风险 $userId = User::where('username', $user)->value('id'); // 如果用户不存在,跳过当前循环 if (!$userId) { continue; } // 调用模型方法直接获取当前用户的订单总价 $totalPrice = Dashboard::getOrdersUserTotal($startDate, $endDate, $userId); // 将当前用户的统计结果添加到集合中 $data->push([ 'username' => $user, 'totalPrice' => $totalPrice ]); } return $data; }
修改后的返回结果
现在返回的结果会完全符合你的期望:
[ {"username": "merijn", "totalPrice": 12345.67}, {"username": "stefan", "totalPrice": 258090.16} ]
额外说明
- 软删除条件修正:之前的
orWhereNull会导致只要任意一个关联表未被软删除就会被查询,现在改为每个表都用whereNull,确保所有关联数据都未被软删除,统计结果更准确。 - 日期处理:使用
Carbon::parse()统一处理日期,避免因日期格式不一致导致的查询错误。
内容的提问来源于stack exchange,提问作者Bogdan Bunea
相关产品推荐
相关产品推荐

