Installation
composer require okeonline/filament-archivable
Publish the config (if needed):
php artisan vendor:publish --provider="Okeonline\FilamentArchivable\FilamentArchivableServiceProvider"
Enable for a Resource Add the trait to your resource class:
use Okeonline\FilamentArchivable\Concerns\HasArchivableActions;
use Okeonline\FilamentArchivable\Concerns\HasArchivableFilters;
class YourResource extends Resource
{
use HasArchivableActions, HasArchivableFilters;
// ...
}
First Use Case
joelbutcher/laravel-archivable.Basic Usage
// In your Resource class
public static function table(Table $table): Table
{
return $table
->columns([
// ...
])
->actions([
ArchiveAction::make(),
UnArchiveAction::make(),
])
->filters([
ArchivedFilter::make(),
]);
}
Customizing Actions
ArchiveAction::make()
->icon('heroicon-o-archive')
->label('Move to Archive');
ArchiveAction::make()
->requiresConfirmation()
->canOnlyArchiveWhen(fn ($record) => auth()->user()->can('archive', $record));
Filter Integration
ArchivedFilter::make()
->label('Show Archived')
->default(false); // Start with non-archived
Bulk Actions
ArchiveAction::make()->bulk(),
UnArchiveAction::make()->bulk(),
Soft-Deletes + Archivable
If your model uses SoftDeletes, ensure the archived_at column is distinct:
use HasArchivableTrait;
use SoftDeletes;
class Model extends Model
{
use HasArchivableTrait, SoftDeletes;
protected $dates = ['archived_at', 'deleted_at'];
}
Custom Archive Logic Override the default behavior via the model:
class Model extends Model
{
use HasArchivableTrait;
public function archive(): void
{
$this->update(['archived_at' => now(), 'custom_status' => 'archived']);
}
}
Resource-Level Configuration
Disable globally in config/filament-archivable.php:
'default' => [
'actions' => false,
'filters' => false,
],
Then enable per-resource:
use HasArchivableActions;
Missing archived_at Column
Column not found: 1054 Unknown column 'archived_at'.joelbutcher/laravel-archivable or add the column manually:
php artisan vendor:publish --provider="JoelButcher\Archivable\ArchivableServiceProvider"
php artisan migrate
Conflicts with SoftDeletes
deleted_at and archived_at are both nullable, queries may behave unexpectedly.public static function getArchivedQuery(): Builder
{
return parent::getArchivedQuery()->whereNull('deleted_at');
}
Permission Denied
canOnlyArchiveWhen or Filament’s built-in policies:
ArchiveAction::make()->canOnlyArchiveWhen(fn ($record) => auth()->user()->can('archive', $record));
Log Queries Enable Laravel query logging to inspect generated SQL:
DB::enableQueryLog();
// Trigger action/filter
tap(DB::getQueryLog(), function ($logs) {
dd($logs);
});
Check Middleware
Ensure joelbutcher/laravel-archivable middleware is registered:
// app/Http/Kernel.php
'archivable' => \JoelButcher\Archivable\Middleware\Archivable::class,
Custom Archive Fields Extend the trait to add custom logic:
class Model extends Model
{
use HasArchivableTrait;
protected static function booted(): void
{
static::archiving(function ($model) {
$model->update(['backup_data' => $model->replicate()]);
});
}
}
Override Filter Behavior
Customize the ArchivedFilter:
class CustomArchivedFilter extends ArchivedFilter
{
protected function setUp(): void
{
parent::setUp();
$this->label('Custom Archive Status');
$this->options([
'active' => 'Active',
'archived' => 'Archived',
'all' => 'All',
]);
}
}
Localization Translate labels/actions:
ArchiveAction::make()
->label(__('filament-archivable::actions.archive'))
->successNotificationMessage(__('filament-archivable::actions.archived'));
Index archived_at
Add an index to the column for faster filtering:
Schema::table('your_table', function (Blueprint $table) {
$table->index('archived_at');
});
Batch Processing For bulk actions, use chunking to avoid memory issues:
UnArchiveAction::make()
->bulk()
->action(function (Collection $records) {
$records->each->restore();
// OR chunked restore:
$records->chunk(100)->each(function ($chunk) {
$chunk->each->restore();
});
});
How can I help you explore Laravel packages today?