FilamentPHP: Grouping Table Rows by Month and Year

Filament's Table builder allows you to group your table rows by date out of the box, but what if you need to group by "month and year"? I encountered this need while working on a project that required viewing purchases grouped by month-year, and after some trial and error, I've figured it out!

Below is the snippet you need:


<?php

use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Grouping\Group;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

class ReceiptResource extends Resource
{
    protected static ?string $model = Purchase::class;

    protected static ?string $label = 'Purchases';

    public static function table(Table $table): Table
    {
        return $table
            ->recordTitleAttribute('vendor_name')
            ->columns([
                // Ex: "Friday 23. September 2023"
                Tables\Columns\TextColumn::make('date')->label('Purchase Date')->date('l j. F Y'),
                Tables\Columns\TextColumn::make('vendor_name')->label('Vendor'),
                Tables\Columns\TextColumn::make('total_amount')->label('Total Amount'),
            ])
            ->defaultGroup(
            // Group the rows by Year and Month (2023-09, 2023-11 etc) instead of "date"
                Group::make('date')
                    // Ex: "2023-10-0",
                    // Note:  You need the "-0" at the end, so Carbon can parse the date.
                    ->getKeyFromRecordUsing(
                        fn(Purchase $record): string => $record->date->format('Y-m-0')
                    )

                    // Ex: "September 2023"
                    ->getTitleFromRecordUsing(
                        fn(Purchase $record): string => $record->date->format('F Y')
                    )

                    // Set the default ordering
                    ->orderQueryUsing(
                        fn(Builder $query, string $direction) => $query->orderBy('date', 'desc')
                    )
                    // Hide "date: " in the Group title
                    ->titlePrefixedWithLabel(false),
            );
    }
}