Resources

Resources are static classes that describe how administrators should be able to interact with data from your app. They are associated with Eloquent models from your app.

To create a resource for the App\Models\Customer model:

php artisan make:filament-resource Customer

This will create several files in the app/Filament/Resources directory:

.
+-- CustomerResource.php
+-- CustomerResource
|   +-- Pages
|   |   +-- CreateCustomer.php
|   |   +-- EditCustomer.php
|   |   +-- ListCustomers.php

Your new resource class lives in CustomerResource.php. Resource classes register forms, tables, authorization settings, and pages associated with that model.

The classes in the Pages directory are used to customize the pages in the admin panel that interact with your resource.

By default, the model associated with your resource is guessed based on the class name of the resource. You may set the static $model property to disable this behaviour:

public static $model = Customer::class;

A label for this resource is generated based on the name of the resource's model. It's used the navigation menu and to display breadcrumbs. You may customize it using the static $label property:

public static $label = 'customer';

Forms

Resource classes contain a static form() method that is used to customize the forms to create and update resource records.

use Filament\Resources\Forms\Form;

public static function form(Form $form)
{
    return $form
        ->schema([
            // ...
        ]);
}

The schema() method is used to define the structure of your form. It is an array of components, in the order they should appear in your form.

For more information, please see the page on Building Forms.

Relations

Managing Single Related Records

The Filament\Resources\Forms\Components\BelongsToSelect field can be used in resource form schemas to create a select element with options to search and select a related record. It has the same methods available as Filament\Resources\Forms\Components\Select, and others to define the relationship and column name that should be used:

Components\BelongsToSelect::make('category_id')
    ->relationship('category', 'name');

This example assumes the following:

  • A category_id foreign key column exists on your parent model.
  • A belongsTo() category relationship on your parent model.
  • A name column on your category model that can be used to render the list of categories to select from.

Sometimes, having a lot of related records as options can cause strain on your web browser. By default, options will only load when you start typing a search. To change this, you may preload() a select field with options. Please only do this if you are certain that there are only a few related records to choose from:

Components\BelongsToSelect::make('category_id')
    ->relationship('category', 'name')
    ->preload();

You may also customize the Query Builder used to get search results by specifying a callback in the third parameter of the relationship() method.

Components\BelongsToSelect::make('category_id')
    ->relationship('category', 'name', function ($query) {
        return $query->where('is_featured', true);
    });

This example will only include featured categories in search results.

Managing Multiple Related Records

Relation managers are components that allow administrators to list, create, attach, edit, detach and delete related records without leaving the parent record's edit page. Resource classes contain a static relations() method that is used to register relation managers for your resource.

To create a relation manager, you can use:

php artisan make:filament-relation-manager CustomerResource orders

This will create a CustomerResource/RelationManagers/OrdersRelationManager.php file. This contains a class where you are able to define a form and table for your relation manager. The relation manager will interact with the orders relationship on your parent model.

You must set the primary column of related records using the static $primaryColumn property on your new relation manager class. The primary column is used to identify related records quickly. This could be a user's name, or a blog post's title.

<?php

namespace App\Filament\Resources\CategoryResource\RelationManagers;

use Filament\Resources\RelationManager;

class PostsRelationManager extends RelationManager
{
    public static $primaryColumn = 'title';

    public static $relationship = 'posts';
}

You must register the new relation manager in your resource's relations() method:

public static function relations()
{
    return [
        RelationManagers\OrdersRelationManager::class,
    ];
}

Once a table and form have been defined for the relation manager, visit the edit page of your resource to see it in action.

HasMany, BelongsToMany and MorphMany relationships are currently fully supported by relation managers.

BelongsToMany relation managers require an extra static $inverseRelationship property set on the class if the existing relationships deviate from traditional naming conventions:

public static $inverseRelationship = 'products';

Tables

Resource classes contain a static table() method that is used to customize the table to list resource records.

use Filament\Resources\Tables\Table;

public static function table(Table $table)
{
    return $table
        ->columns([
            // ...
        ])
        ->filters([
            // ...
        ]);
}

The columns() method is used to define the columns in your table. It is an array of column objects, in the order they should appear in your table.

Filters are predefined scopes that administrators can use to filter records in your table. The filters() method is used to register these.

For more information, please see the page on Building Tables.

Pages

Pages are classes that are associated with a resource. They are essentially Laravel Livewire components with custom integration utilities for use with Filament.

Page class files are in the /Pages directory of your resource directory.

By default, resources are generated with three pages:

  • List has a table for displaying, searching and deleting resource records. From here, you are able to access the create and edit pages. It is routed to /.
  • Create has a form that is able to create a resource record. It is routed to /create.
  • Edit has a form that is able to update a resource record, along with the relation managers registered to your resource. It is routed to /{record}/edit.

Customizing Default Pages

You are able to customize text used in the default pages by overriding properties on the page class. To see the options available, check the static properties defined in the parent class of each default page.

For further customization opportunities, you can override the static $view property on your page to a custom view in your app:

public static $view = 'customers.list-records';

Hooks

Hooks may be used to customize the behaviour of a default page. To set up a hook, create a protected method on the page class with the name of the hook:

protected function beforeSave()
{
    // ...
}

In this example, the code in the beforeSave() method will be called before the data in the form is saved to the database.

There are several available hooks for the create and edit pages:

use Filament\Resources\Pages\CreateRecord;

class CreateCustomer extends CreateRecord
{
    // ...

    protected function beforeFill()
    {
        // Runs before the form fields are populated with their default values.
    }

    protected function afterFill()
    {
        // Runs after the form fields are populated with their default values.
    }

    protected function beforeValidate()
    {
        // Runs before the form fields are validated when the form is submitted.
    }

    protected function afterValidate()
    {
        // Runs after the form fields are validated when the form is submitted.
    }

    protected function beforeCreate()
    {
        // Runs before the form fields are saved to the database.
    }

    protected function afterCreate()
    {
        // Runs after the form fields are saved to the database.
    }
}
use Filament\Resources\Pages\EditRecord;

class EditCustomer extends EditRecord
{
    // ...

    protected function beforeFill()
    {
        // Runs before the form fields are populated from the database.
    }

    protected function afterFill()
    {
        // Runs after the form fields are populated from the database.
    }

    protected function beforeValidate()
    {
        // Runs before the form fields are validated when the form is saved.
    }

    protected function afterValidate()
    {
        // Runs after the form fields are validated when the form is saved.
    }

    protected function beforeSave()
    {
        // Runs before the form fields are saved to the database.
    }

    protected function afterSave()
    {
        // Runs after the form fields are saved to the database.
    }

    protected function beforeDelete()
    {
        // Runs before the record is deleted.
    }

    protected function afterDelete()
    {
        // Runs after the record is deleted.
    }
}

Custom Pages

Filament allows you to create completely custom pages for resources. To create a new page, you can use:

php artisan make:filament-page SortCustomers --resource=CustomerResource

This command will create two files - a page class in the /Pages directory of your resource directory, and a view in the /pages directory of the resource views directory.

You must register custom pages to a route in the static routes() method of your resource:

public static function routes()
{
    return [
        // ...
        Pages\SortCustomers::routeTo('/sort', 'sort'),
    ];
}

The first parameter of the routeTo() method is the path of the route, and the second is its name. Any parameters defined in the route's path will be available to the page class, in an identical way to Livewire.

To generate a URL for a resource route, you may call the static generateUrl() method on the page class:

SortCustomers::generateUrl($parameters = [], $absolute = true);

Authorization

For authorization, Filament will observe any model policies that are registered in your app. The viewAny action may be used to completely disable resources and remove them from the navigation menu.

Filament also includes a powerful role-based authorization system, which is set up out of the box with the default users table. You may also implement roles functionality in a custom users table.

You may create roles, such as Manager, using:

php artisan make:filament-role Manager

Administrators will now be able to assign this role to any Filament user through the admin panel.

To only allow users with the Manager role to access a resource, declare so in the static authorization() method:

use App\Filament\Roles;

public static function authorization()
{
    return [
        Roles\Manager::allow(),
    ];
}

You may authorize as many roles as you wish.

Please note: administrators will always have full access to every resource in your admin panel.

You may want to only deny users with the Manager role from accessing this resource. To do this, you may use the static deny() method instead:

use App\Filament\Roles;

public static function authorization()
{
    return [
        Roles\Manager::deny(),
    ];
}

You may specify only() certain actions that roles have access to. These follow the same naming conventions as methods in a policy.

use App\Filament\Roles;

public static function authorization()
{
    return [
        Roles\Manager::allow()->only(['viewAny', 'create']),
    ];
}

There is also the possibility to allow access to all actions except() those specified:

use App\Filament\Roles;

public static function authorization()
{
    return [
        Roles\Manager::allow()->except(['delete']),
    ];
}