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

Laravel 8在Mint系统中出现Symfony执行超时错误求助(关联polyfill-mbstring)

解决Laravel 8项目在Mint系统的超时问题

首先,虽然错误提示显示在symfony/polyfill-mbstring/Mbstring.php的632行,但这只是超时发生的“现场”,真正的根源是你的控制器代码存在大量低效的数据库查询(N+1查询问题),而Mint系统的PHP默认max_execution_time限制可能比Ubuntu更严格,所以触发了超时。下面分临时解决方案和根本优化方案来说:

一、临时应急:调整PHP执行时间限制

如果需要快速让项目运行起来,可以先修改PHP的执行时间配置:

  • 找到你的PHP配置文件:在终端执行php --ini,找到Loaded Configuration File对应的路径(比如/etc/php/8.0/cli/php.ini)
  • 编辑该文件,找到max_execution_time配置项,把默认的60改成120甚至更高(比如max_execution_time = 120)
  • 如果你用的是Laravel内置开发服务器,重启服务器即可生效;如果用的是Nginx/Apache,需要重启对应的服务

或者也可以在控制器开头临时设置:

ini_set('max_execution_time', 120); // 设置为120秒

不过这只是权宜之计,随着数据量增长,超时问题还会再次出现,所以必须优化代码。

二、根本解决方案:优化数据库查询

你的控制器代码里存在多处循环嵌套数据库查询的情况,每一次循环都会发起新的数据库请求,这会导致执行时间指数级增长。下面针对你的代码逐一优化:

1. 优化日期去重逻辑

原来的代码通过PHP循环去重日期,改成直接在数据库层面分组去重:

$compressed_date = Report::where('store_id', $store->id)
    ->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
    ->selectRaw('DATE(created_at) as created_at')
    ->distinct()
    ->get()
    ->map(function($item) {
        return [
            'created_at' => $item->created_at,
            'formated' => Carbon::parse($item->created_at)->format('m/d/Y')
        ];
    });

2. 优化周产品统计逻辑

原来的map方法里每个Report都发起一次查询,改成一次性分组统计所有SKU的周总量:

use Illuminate\Support\Facades\DB;

// 1. 一次性统计本周每个SKU的总数量
$weeklySkuCounts = Report::where('store_id', $store->id)
    ->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
    ->select('product_sku', DB::raw('COUNT(*) as weekly_amount'))
    ->groupBy('product_sku')
    ->get()
    ->keyBy('product_sku');

// 2. 一次性获取每个SKU对应的产品信息
$skuProductDetails = Report::where('store_id', $store->id)
    ->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
    ->select('product_name', 'product_variant', 'product_sku')
    ->distinct()
    ->get()
    ->keyBy('product_sku');

// 3. 合并成需要的数组
$compressed_weekly_product = collect();
foreach ($weeklySkuCounts as $sku => $countData) {
    $product = $skuProductDetails[$sku];
    $compressed_weekly_product->push([
        'product_name' => $product->product_name,
        'product_variant' => $product->product_variant,
        'product_sku' => $sku,
        'weekly_amount' => $countData->weekly_amount
    ]);
}

3. 优化每日数量统计逻辑

原来的双重循环里每次都发起查询,改成一次性获取所有SKU的每日数据:

// 获取所有需要统计的日期
$targetDates = $compressed_date->pluck('created_at')->toArray();

// 一次性查询所有SKU的每日数量
$dailySkuStats = Report::where('store_id', $store->id)
    ->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])
    ->select('product_sku', DB::raw('DATE(created_at) as date'), DB::raw('COUNT(*) as daily_count'))
    ->groupBy('product_sku', 'date')
    ->get()
    ->groupBy('product_sku');

// 填充每个SKU的每日数量
$compressed_weekly_product = $compressed_weekly_product->map(function($item) use ($dailySkuStats, $targetDates) {
    $skuDailyData = $dailySkuStats->get($item['product_sku'], collect());
    $dailyAmount = [];
    foreach ($targetDates as $date) {
        // 找不到对应日期的数据就填0
        $dailyAmount[] = $skuDailyData->where('date', $date)->first()?->daily_count ?? 0;
    }
    $item['daily_amount'] = $dailyAmount;
    return $item;
});

4. 优化视图统计数据的获取

原来用sizeof(Model::get())的方式会把所有数据加载到内存再统计,改成用数据库的count()方法:

return view('panel.outlet.dashboard.index', [
    'is_dashboard'=>true,
    'total_customer'=>Customer::where('store_id',$store->id)->count(),
    'total_revenue'=>Order::where('store_id',$store->id)->whereIn('status',['2','3','-'])->sum('total_amount'),
    'total_order'=>Order::where('store_id',$store->id)->count(),
    'total_sales'=>Order::where('store_id',$store->id)->whereIn('status',['2','3','-'])->count(),
    'total_product'=>Product::where('store_id',$store->id)->count(),
    'total_sales_income'=>Order::where('store_id',$store->id)->whereIn('status',['2','3','-'])->sum('total_amount'),
    'growth_percentage'=>round($growth_percentage,2),
    'lastest_order'=>Order::where(['store_id'=>$store->id,'type'=>'app'])->orderBy('id','DESC')->limit(10)->get(),
    'report_date'=>$compressed_date,
    'top_weekly_product'=>$top_weekly_product,
    'weekly_product'=>$compressed_weekly_product,
    'weekly_report'=>DailyReport::where('store_id',$store->id)->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()])->get()
]);

三、额外建议

  • 可以开启Laravel的查询日志(DB::enableQueryLog()),对比优化前后的查询数量,直观看到优化效果
  • 给常用的查询字段(比如store_id、product_sku、created_at)添加数据库索引,进一步提升查询速度

经过这些优化后,你的代码执行时间会大幅降低,无论是在Mint还是Ubuntu系统上都能流畅运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:32:38