martinpetricko/filament-restore-or-create
Install the Package
composer require martinpetricko/filament-restore-or-create
Publish the config (if needed):
php artisan vendor:publish --provider="MartinPetricko\FilamentRestoreOrCreate\FilamentRestoreOrCreateServiceProvider"
Register the Plugin
Add to your app/Providers/Filament/AdminPanelProvider.php:
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
\MartinPetricko\FilamentRestoreOrCreate\FilamentRestoreOrCreatePlugin::make(),
]);
}
First Use Case Apply to a Filament Resource by adding the trait to your model:
use MartinPetricko\FilamentRestoreOrCreate\Traits\RestoreOrCreate;
class Post extends Model
{
use RestoreOrCreate;
}
Ensure your model uses soft deletes (SoftDeletes trait) and has a deleted_at column.
Form Submission When a user submits a create form, the package intercepts the request and checks for soft-deleted records matching the input data.
Detection Logic
Override getSimilarRecords() in your model to define matching criteria:
public function getSimilarRecords(array $attributes): Collection
{
return static::where('title', $attributes['title'])
->whereNull('deleted_at')
->get();
}
Default behavior uses where() on all fillable fields.
Modal Presentation If matches are found, a modal displays:
getRestoreModalContent()).restore() on the model).Fallback to Create If no matches or user declines, the original create logic proceeds.
getRestoreModalContent() in your model:
public function getRestoreModalContent(SoftDeletingModel $record): string
{
return view('custom.restore-modal', ['record' => $record]);
}
'enabled_for' => [
'App\Models\Post', // Only enable for Post model
],
registerCreateActions() in your Resource.Soft Deletes Required
The package only works with soft-deleted models. Ensure your model uses SoftDeletes and has deleted_at column.
Case-Sensitive Matching
Default getSimilarRecords() uses exact matches. For case-insensitive searches:
return static::whereRaw("LOWER(title) = LOWER('{$attributes['title']}')")
->whereNull('deleted_at')
->get();
Performance on Large Tables
Avoid complex queries in getSimilarRecords(). Add indexes to frequently queried columns:
php artisan schema:dump
Then manually add indexes in migrations.
Caching Conflicts If using Filament’s caching, clear it after restoring a record to avoid stale data:
public function restore()
{
$this->forceFill(['deleted_at' => null])->save();
Cache::forget('filament-resource-cache-key');
}
### Debugging
- **Log Detection Queries**
Enable debug mode in config:
```php
'debug' => env('FILAMENT_RESTORE_OR_CREATE_DEBUG', false),
Check logs for SQL queries during detection.
RestoreOrCreate trait.Custom Matching Logic
Extend the RestoreOrCreate trait to add fuzzy matching (e.g., Levenshtein distance):
use Similarity\Similarity;
public function getSimilarRecords(array $attributes): Collection
{
return static::where('title', 'like', "%{$attributes['title']}%")
->whereNull('deleted_at')
->where(function ($query) use ($attributes) {
$query->orWhere('slug', Similarity::levenshtein($attributes['slug']), '<', 3);
})
->get();
}
Post-Restore Redirects
Override getRestoreRedirectUrl() in your model:
public function getRestoreRedirectUrl(SoftDeletingModel $record): string
{
return route('filament.resources.posts.edit', $record);
}
Disable for Specific Fields Exclude fields from matching in config:
'ignore_fields' => ['created_at', 'updated_at'],
How can I help you explore Laravel packages today?