amjadiqbal/filament-deleted-records
A Filament plugin that adds a dedicated panel resource for browsing, filtering, and restoring soft-deleted Eloquent records. Quickly inspect trashed data, view deleted items, and restore or force-delete them without leaving the admin panel.
Install the package with Composer and register the plugin in your Filament panel provider:
composer require amjadiqbal/filament-deleted-records
php artisan vendor:publish --tag="filament-deleted-records-config"
// app/Providers/Filament/AdminPanelProvider.php
->plugin(DeletedRecordsPlugin::make())
The first place to look is the published config file. Add the soft-deletable models you want exposed, and review the masking and authorization options before opening the page. The second place is the README/docs at https://amjad.com.pk/filament/plugins/filament-deleted-records, especially the v1.0.1 notes on defaults and limitations.
Your first use case should be: register one model, open the Deleted Records page, search for a known trashed record, preview it, and restore it. Before you let anyone else near the page, add a policy or callback for restore and permanent delete — the default is permissive.
v1.0.1 is a security release. Upgrade before exposing the page to non-admin panel users, because earlier versions allowed search to probe masked values.
Register models deliberately. Only add models that use SoftDeletes and that you actually want panel users to see. The config is the source of truth for what appears in the page.
Authorize through policies, not hope. Define restore and forceDelete abilities on each model's policy. This is the cleanest extension point and keeps authorization auditable:
class InvoicePolicy
{
public function restore(User $user, Invoice $invoice): bool
{
return $user->hasRole('admin');
}
public function forceDelete(User $user, Invoice $invoice): bool
{
return $user->hasRole('super-admin');
}
}
Use config callbacks only when a policy is impractical. Prefer policies for anything long-lived.
Treat bulk actions as a reporting workflow. Bulk restore and bulk permanent delete now report records skipped for permission separately from failed restores. Surface both counts in your UI or logs. If you have tests asserting a single "restored" count, update them.
Configure masking for previews. Add sensitive attributes (password hashes, tokens, personal data) to the mask list. Understand that this is a display-layer control, not encryption or redaction at rest.
Handle tenancy explicitly. If your panel uses Filament tenancy, verify that the plugin scopes records to the current tenant. Test with a second tenant: can a user see, restore, or purge a record belonging to another tenant? The README covers tenancy but does not replace your own test.
Search behavior is now narrower and safer. Search matches configured keys/title attributes and never masked attributes. If users need richer search, add a dedicated searchable column or extend the page rather than reintroducing JSON-wide matching.
Test against your production database driver. The package runs its own suite on MySQL 9.7, Postgres 17, and SQLite via DB_TEST_DRIVER. Run your application tests on the same driver you deploy, because JSON and case-insensitive search behavior differ across databases.
Upgrade routine. Run composer update, then php artisan config:clear, review any republished config, and re-run tests covering search, masking, bulk actions, and tenancy.
LIKE, allowing a user to probe masked values such as password hashes. v1.0.1 fixes this.How can I help you explore Laravel packages today?