Skip to main content

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
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.

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();
    }
}

Form Schemas

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(),
        ]);
}
You can also define forms directly in the resource class:
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;

public static function form(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
You can specify an Eloquent accessor if a single column isn’t sufficient.

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');
}
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;
1

Set the icon

Use any Blade component name. Heroicons are included by default.
protected static ?string $navigationIcon = 'heroicon-o-shopping-cart';
2

Group related items

Group multiple resources under a common label:
protected static ?string $navigationGroup = 'Shop';
3

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.

Build docs developers (and LLMs) love