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
相关产品推荐
相关产品推荐

