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

Laravel+Filament报表Widget中report_year丢失致SQL报错问题

解决Laravel+Filament报表Widget分组时report_year字段丢失问题

问题原因

Filament在执行计数查询(比如用于统计总数、分页逻辑)时,会自动重置查询的select子句为count(*),导致你通过selectRaw('year(created_at) as report_year')定义的别名字段被丢弃,分组时自然找不到report_year,触发字段不存在的错误。关闭MySQL严格模式无效是因为这不是SQL语法严格性问题,而是Filament的查询重写逻辑导致的。

解决方案

方案1:直接用原生函数分组(推荐)

不要使用别名分组,直接在groupBy里写year(created_at)的原生SQL,这样无论Filament是否重写select子句,分组逻辑都能正常识别:

use Illuminate\Support\Facades\DB;

// 正确的查询写法
$query->selectRaw('year(created_at) as report_year, count(*) as total')
      ->groupBy(DB::raw('year(created_at)'));

方案2:手动适配Filament的计数查询逻辑

如果必须使用别名分组,可以在Widget的query方法中判断当前是否是计数查询,手动补充必要的字段:

use Illuminate\Database\Eloquent\Builder;

public function query(): Builder
{
    $query = YourModel::query();

    // 检查当前查询是否是Filament的计数查询
    $isCountQuery = str_contains($query->toSql(), 'count(');

    if (!$isCountQuery) {
        // 普通数据查询:保留自定义字段
        $query->selectRaw('year(created_at) as report_year, count(*) as total');
    } else {
        // 计数查询:必须包含分组字段,否则分组报错
        $query->selectRaw('year(created_at) as report_year, count(*) as aggregate');
    }

    return $query->groupBy('report_year');
}

方案3:使用selectSub定义分组字段

通过Laravel的selectSub方法将年份字段定义为子查询,这样别名report_year会被视为合法的分组字段,Filament计数时不会丢失:

$query->selectSub(function ($subQuery) {
        $subQuery->selectRaw('year(created_at)')->from('your_table_name')->whereColumn('your_table_name.id', 'main_table.id');
    }, 'report_year')
    ->selectRaw('count(*) as total')
    ->groupBy('report_year');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:42:13