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

Filament PHP v3:如何让Dashboard筛选表单数据供Widget调用

在Filament PHP v3中实现Dashboard筛选条件与Widget的数据共享

步骤1:修改Dashboard传递筛选参数

在Dashboard.php中给日期选择器添加实时更新,并通过getWidgets()方法把筛选条件传递给目标Widget:

<?php

namespace App\Filament\Pages;

use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Section;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Pages\Dashboard as BaseDashboard;

class Dashboard extends BaseDashboard
{
    use BaseDashboard\Concerns\HasFiltersForm;

    public function getColumns(): int | string | array
    {
        return 2;
    }

    public function filtersForm(Form $form): Form
    {
        return $form
            ->schema([
                Section::make()
                    ->schema([
                        DatePicker::make('startDate')
                            ->maxDate(fn (Get $get) => $get('endDate') ?: now())
                            ->live(), // 实时同步筛选值
                        DatePicker::make('endDate')
                            ->minDate(fn (Get $get) => $get('startDate') ?: now())
                            ->maxDate(now())
                            ->live(), // 实时同步筛选值
                    ])
                    ->columns(2),
            ]);
    }

    // 重写getWidgets传递筛选参数
    protected function getWidgets(): array
    {
        return [
            \App\Filament\Widgets\KeyMetricsOverview::class => [
                'startDate' => $this->filters['startDate'] ?? null,
                'endDate' => $this->filters['endDate'] ?? null,
            ],
            \App\Filament\Widgets\CustomersChart::class => [
                'startDate' => $this->filters['startDate'] ?? null,
                'endDate' => $this->filters['endDate'] ?? null,
            ],
        ];
    }
}

步骤2:修改CustomersChart接收并使用筛选参数

在CustomersChart.php中添加公共属性接收日期参数,在数据查询中应用筛选条件:

<?php

namespace App\Filament\Widgets;

use Filament\Widgets\ChartWidget;
use Carbon\Carbon;
use App\Models\Customer;

class CustomersChart extends ChartWidget
{
    protected static ?string $heading = 'Customers';
    protected static ?int $sort = 3;
    public ?string $filter = 'today';
    
    // 声明接收筛选条件的公共属性
    public ?Carbon $startDate = null;
    public ?Carbon $endDate = null;

    protected function getData(): array
    {
        // 构建带时间筛选的查询
        $query = Customer::query();
        
        if ($this->startDate) {
            $query->where('created_at', '>=', $this->startDate);
        }
        
        if ($this->endDate) {
            $query->where('created_at', '<=', $this->endDate->endOfDay());
        }

        // 按月份分组统计客户数量(替换为你的业务逻辑)
        $monthlyData = $query->selectRaw('MONTH(created_at) as month, COUNT(*) as count')
            ->groupBy('month')
            ->orderBy('month')
            ->pluck('count', 'month')
            ->toArray();

        // 补全12个月的空数据
        $labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
        $filledData = array_map(fn($month) => $monthlyData[$month] ?? 0, range(1, 12));

        return [
            'datasets' => [
                [
                    'label' => 'Blog posts created',
                    'data' => $filledData,
                ],
                [
                    'label' => 'Blog posts created 2',
                    'data' => $filledData,
                ],
            ],
            'labels' => $labels,
        ];
    }

    protected function getType(): string
    {
        return 'line';
    }

    protected function getFilters(): ?array
    {
        return [
            'today' => 'Today',
            'week' => 'Last week',
            'month' => 'Last month',
            'year' => 'This year',
        ];
    }

    // 兼容Widget自身筛选逻辑
    public function mount(): void
    {
        parent::mount();
        
        if (!$this->startDate || !$this->endDate) {
            switch ($this->filter) {
                case 'today':
                    $this->startDate = Carbon::today();
                    $this->endDate = Carbon::today()->endOfDay();
                    break;
                case 'week':
                    $this->startDate = Carbon::now()->subWeek();
                    $this->endDate = Carbon::now();
                    break;
                case 'month':
                    $this->startDate = Carbon::now()->subMonth();
                    $this->endDate = Carbon::now();
                    break;
                case 'year':
                    $this->startDate = Carbon::now()->startOfYear();
                    $this->endDate = Carbon::now();
                    break;
            }
        }
    }
}

步骤3:修改KeyMetricsOverview接收并使用筛选参数

在KeyMetricsOverview.php中添加公共属性,更新统计逻辑:

<?php

namespace App\Filament\Widgets;

use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Carbon\Carbon;
use App\Models\Customer;

class KeyMetricsOverview extends BaseWidget
{
    protected static ?int $sort = 1;
    
    // 声明接收筛选条件的公共属性
    public ?Carbon $startDate = null;
    public ?Carbon $endDate = null;

    protected function getColumns(): int
    {
        return 2;
    }

    protected function getStats(): array
    {
        // 构建带时间筛选的查询
        $query = Customer::query();
        
        if ($this->startDate) {
            $query->where('created_at', '>=', $this->startDate);
        }
        
        if ($this->endDate) {
            $query->where('created_at', '<=', $this->endDate->endOfDay());
        }

        // 计算客户流失率(替换为你的业务逻辑)
        $totalCustomers = $query->count();
        $churnedCustomers = $query->where('status', 'churned')->count();
        $churnRate = $totalCustomers > 0 ? number_format(($churnedCustomers / $totalCustomers) * 100, 2) . '%' : '0%';
        
        // 计算平均客户生命周期(替换为你的业务逻辑)
        $avgLifetime = $query->avg('lifetime_months') ?? 0;
        $avgLifetimeFormatted = number_format($avgLifetime, 3) . ' months';

        return [
            Stat::make('Customer churn', $churnRate)
                ->description('57.5%')
                ->descriptionIcon('heroicon-m-arrow-trending-up')
                ->color('danger'),
            Stat::make('Avg. customer lifetime', $avgLifetimeFormatted)
                ->description('-36.51%')
                ->descriptionIcon('heroicon-m-arrow-trending-up')
                ->color('danger'),
        ];
    }
}

核心说明

  • ->live():让日期选择器的变化实时同步到Dashboard的filters属性,无需手动提交。
  • 参数传递:通过getWidgets()中的数组参数,Filament会自动将值赋值给Widget的对应公共属性。
  • 逻辑兼容:如果Widget自身有筛选逻辑,可在mount()方法中处理默认值,优先使用Dashboard传递的筛选条件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:14:55