What are Resources?
Resources are static classes that build complete CRUD (Create, Read, Update, Delete) interfaces for your Eloquent models. They describe how administrators interact with data using forms, tables, and pages.
Each resource in Filament:
Connects to an Eloquent model
Defines form schemas for creating and editing records
Configures table layouts for listing records
Manages multiple pages (List, Create, Edit, View)
Handles relationships with other models
Resources use a declarative API pattern. You define what you want, and Filament handles the implementation details.
Creating a Resource
To create a resource for the App\Models\Customer model:
php artisan make:filament-resource Customer
This creates several files in app/Filament/Resources:
Customers/
├── CustomerResource.php # Main resource class
├── Pages/
│ ├── CreateCustomer.php # Create page
│ ├── EditCustomer.php # Edit page
│ └── ListCustomers.php # List page
├── Schemas/
│ └── CustomerForm.php # Form definition
└── Tables/
└── CustomersTable.php # Table configuration
Simple Resource
With View Page
With Soft Deletes
For models that only need basic CRUD in modals: php artisan make:filament-resource Customer --simple
This creates a single “Manage” page with modal-based create/edit operations. To add a read-only View page: php artisan make:filament-resource Customer --view
For models using soft deletes: php artisan make:filament-resource Customer --soft-deletes
Resource Structure
The Resource Class
Your main resource class (CustomerResource.php) contains configuration and references to other components:
packages/panels/src/Resources/Resource.php
use Filament\Resources\ Resource ;
abstract class Resource
{
protected static ? string $model = null ;
public static function form ( Schema $schema ) : Schema
{
return $schema ;
}
public static function table ( Table $table ) : Table
{
return $table ;
}
public static function getEloquentQuery () : Builder
{
return static :: getModel () :: query ();
}
}
Forms define how users create and edit records. By default, form definitions live in separate schema files:
use Filament\Forms\Components\ TextInput ;
use Filament\Schemas\ Schema ;
public static function configure ( Schema $schema ) : Schema
{
return $schema
-> components ([
TextInput :: make ( 'name' ) -> required (),
TextInput :: make ( 'email' ) -> email () -> required (),
]);
}
Tables
Tables display records on the List page. Like forms, they can be defined in separate files or inline:
use Filament\Tables\Columns\ TextColumn ;
use Filament\Tables\ Table ;
public static function configure ( Table $table ) : Table
{
return $table
-> columns ([
TextColumn :: make ( 'name' ),
TextColumn :: make ( 'email' ),
]);
}
Record Titles
Set a $recordTitleAttribute to identify records throughout the UI:
protected static ? string $recordTitleAttribute = 'name' ;
This is used in:
Global search results
Breadcrumbs
Delete confirmation modals
Relationship selects
Model Labels
Filament automatically generates labels from your model name. Customize them if needed:
protected static ? string $modelLabel = 'client' ;
protected static ? string $pluralModelLabel = 'clients' ;
For dynamic labels:
public static function getModelLabel () : string
{
return __ ( 'filament/resources/customer.label' );
}
public static function getPluralModelLabel () : string
{
return __ ( 'filament/resources/customer.plural_label' );
}
Navigation
Resources automatically appear in the navigation menu. Customize the navigation item:
protected static ? string $navigationIcon = 'heroicon-o-user-group' ;
protected static ? string $navigationLabel = 'My Customers' ;
protected static ? string $navigationGroup = 'Shop' ;
protected static ? int $navigationSort = 2 ;
Set the icon
Use any Blade component name. Heroicons are included by default. protected static ? string $navigationIcon = 'heroicon-o-shopping-cart' ;
Group related items
Group multiple resources under a common label: protected static ? string $navigationGroup = 'Shop' ;
Control the order
Lower numbers appear first: protected static ? int $navigationSort = 1 ;
Customizing the Eloquent Query
Every query to your resource starts with getEloquentQuery(). Override it to apply global constraints:
packages/panels/src/Resources/Resource.php
public static function getEloquentQuery () : Builder
{
return parent :: getEloquentQuery () -> where ( 'is_active' , true );
}
Disabling Global Scopes
Remove all global scopes:
public static function getEloquentQuery () : Builder
{
return parent :: getEloquentQuery () -> withoutGlobalScopes ();
}
Or remove specific scopes:
public static function getEloquentQuery () : Builder
{
return parent :: getEloquentQuery ()
-> withoutGlobalScopes ([ ActiveScope :: class ]);
}
Generating URLs
Use getUrl() to generate URLs to resource pages:
// List page
CustomerResource :: getUrl (); // /admin/customers
// Create page
CustomerResource :: getUrl ( 'create' ); // /admin/customers/create
// Edit page
CustomerResource :: getUrl ( 'edit' , [ 'record' => $customer ]); // /admin/customers/edit/1
// View page
CustomerResource :: getUrl ( 'view' , [ 'record' => $customer ]); // /admin/customers/1
URLs for Modals
Generate URLs that open modals:
use Filament\Actions\ EditAction ;
CustomerResource :: getUrl ( parameters : [
'tableAction' => EditAction :: getDefaultName (),
'tableActionRecord' => $customer ,
]); // /admin/customers?tableAction=edit&tableActionRecord=1
Authorization
Filament respects Laravel model policies :
viewAny() - Controls resource visibility in navigation
create() - Controls access to Create page
update() - Controls access to Edit page
view() - Controls access to View page
delete() - Controls delete actions
deleteAny() - Controls bulk delete actions
forceDelete() / forceDeleteAny() - Controls force delete for soft-deleted records
restore() / restoreAny() - Controls restore for soft-deleted records
If you have a model policy, you must return true from viewAny() for the resource to appear in navigation.
Skipping Authorization
protected static bool $shouldSkipAuthorization = true ;
Pages
Resources consist of multiple pages defined in getPages():
public static function getPages () : array
{
return [
'index' => ListCustomers :: route ( '/' ),
'create' => CreateCustomer :: route ( '/create' ),
'edit' => EditCustomer :: route ( '/{record}/edit' ),
'view' => ViewCustomer :: route ( '/{record}' ),
];
}
You can delete pages you don’t need. Just remove the file and its entry from getPages().
Auto-Generating Resources
Filament can inspect your database and generate forms and tables automatically:
php artisan make:filament-resource Customer --generate
This works best with well-structured databases that follow Laravel conventions.