Installation
composer require a909m/filament-statefusion
Publish the config (if needed):
php artisan vendor:publish --provider="A909M\FilamentStateFusion\FilamentStateFusionServiceProvider"
Register the Plugin
Add to app/Providers/Filament/AdminPanelProvider.php:
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
\A909M\FilamentStateFusion\FilamentStateFusionPlugin::make(),
]);
}
First Use Case: Display States in a Resource
For a Post model with states (e.g., draft, published), annotate the resource:
use A909M\FilamentStateFusion\Concerns\HasStates;
class PostResource extends Resource
{
use HasStates;
// ...
}
States will auto-render in the table, form, and detail views.
State-Aware Tables Filter records by state in the table view:
public static function table(Table $table): Table
{
return $table
->columns([
// ...
StatesColumn::make('state'),
]);
}
State Transitions in Forms Add a state transition button to forms:
public static function form(Form $form): Form
{
return $form
->schema([
// ...
StatesWidget::make('state')
->transitions([
'publish' => 'Publish',
'draft' => 'Save as Draft',
]),
]);
}
State-Based Permissions Restrict state transitions via Filament policies:
public function canPublish(Post $record): bool
{
return $record->state->is('draft');
}
Custom State Logic Extend state behavior in the model:
class Post extends Model
{
use \Spatie\ModelStates\HasStates;
protected $states = [
'draft' => ['color' => 'gray-500'],
'published' => ['color' => 'green-500'],
];
public function publish(): void
{
$this->transitionTo('published');
// Additional logic (e.g., notify subscribers)
}
}
Bulk State Actions Add bulk state transitions to table actions:
public static function table(Table $table): Table
{
return $table
->actions([
Tables\Actions\BulkAction::make('publish')
->action(function (Collection $records) {
foreach ($records as $record) {
$record->transitionTo('published');
}
}),
]);
}
State Not Reflecting in UI
HasStates trait from Spatie, not a custom implementation.php artisan optimize:clear
Transition Buttons Missing
states array in the model includes the transition targets.canPublish policy).Stale State Colors
$states array or via the StatesWidget:
StatesWidget::make('state')
->colors([
'draft' => 'amber-500',
'published' => 'emerald-500',
])
Performance with Large Datasets
eagerLoadStates() in the resource’s getTableRecords() to avoid N+1 queries:
public static function getTableRecords(Table $table): Collection
{
return Post::query()
->withStates()
->get();
}
Log State Transitions Add a model observer to track transitions:
class PostStateObserver
{
public function transitioned(Post $post, string $from, string $to)
{
\Log::info("State transition: {$from} -> {$to}", ['post_id' => $post->id]);
}
}
Inspect Filament StateFusion Events
Listen for state-related events in EventServiceProvider:
protected $listen = [
\A909M\FilamentStateFusion\Events\StateTransitioning::class => [
function ($event) {
\Log::debug('Transitioning state', $event->state);
},
],
];
Custom State Widgets Create a custom widget for complex state logic:
class CustomStatesWidget extends StatesWidget
{
protected function getTransitions(): array
{
return [
'approve' => Translatable::make('Approve'),
'reject' => Translatable::make('Reject'),
];
}
}
State-Based Table Filters Dynamically filter tables by state:
public static function getTableFilters(Table $table): array
{
return [
\A909M\FilamentStateFusion\Tables\Filters\StateFilter::make('state')
->states(['draft', 'published']),
];
}
Integrate with Filament Actions Trigger state transitions from custom actions:
Tables\Actions\Action::make('archive')
->action(function (Post $record) {
$record->transitionTo('archived');
$record->save();
}),
Localization Translate state labels and transitions:
StatesWidget::make('state')
->translatable()
->translations([
'draft' => 'Rascunho',
'published' => 'Publicado',
]),
How can I help you explore Laravel packages today?