Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як побудувати віджет-графік у Filament з даних Eloquent і додати фільтр періоду?

Графіки у Filament малюються бібліотекою Chart.js. Віджет повертає дані в її форматі.

php artisan make:filament-widget OrdersChart --chart
use Filament\Widgets\ChartWidget;

class OrdersChart extends ChartWidget
{
    protected ?string $heading = 'Замовлення';

    protected ?string $pollingInterval = null;   // історичним даним опитування не потрібне

    public ?string $filter = 'month';

    protected function getFilters(): ?array
    {
        return [
            'week' => 'Тиждень',
            'month' => 'Місяць',
            'year' => 'Рік',
        ];
    }

    protected function getData(): array
    {
        $days = match ($this->filter) {
            'week' => 7,
            'year' => 365,
            default => 30,
        };

        $rows = Order::query()
            ->where('created_at', '>=', now()->subDays($days))
            ->selectRaw('DATE(created_at) as day, COUNT(*) as total')
            ->groupBy('day')
            ->orderBy('day')
            ->pluck('total', 'day');

        return [
            'datasets' => [
                ['label' => 'Замовлення', 'data' => $rows->values()->all()],
            ],
            'labels' => $rows->keys()->all(),
        ];
    }

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

Типи графіків: line, bar, pie, doughnut, radar, polarArea, bubble, scatter. Опції Chart.js - через getOptions().

Готове рішення для часових рядів - пакет flowframe/laravel-trend, який рекомендує документація: Trend::model(Order::class)->between(...)->perDay()->count() повертає значення й дні без даних (агрегат з GROUP BY дні без замовлень просто пропускає, і графік виходить нерівномірним).

Пастки:

  • $filter - публічна властивість Livewire, її значення приходить з браузера. Використовувати її лише через match з відомими варіантами, а не підставляти в запит напряму;
  • опитування за замовчуванням - кожні 5 секунд. Агрегат за рік щоп'ять секунд на кожному відкритому дашборді - марне навантаження. Для історичних графіків опитування вимикають;
  • важкі агрегати - кешувати з ключем, що містить фільтр, або рахувати заздалегідь у таблицю статистики;
  • DATE(created_at) групує за часовим поясом бази - якщо база в UTC, а користувачі в Києві, межі днів «зсунуться».

Докладніше в документації: Віджети-графіки

Схожі питання