Support the ongoing development of Laravel.io →
Article Hero Image

Filamentphp: a first look

26 Jun, 2023 7 min read

Photo by Ryan Quintal on Unsplash

As Laravel developers we know how productive a framework can be: It provides a set of common components, reusable functionality and most importantly, a set of guidelines that make everyone using the framework more efficient.

Knowing this, the fine folks over at FilamentPHP created a framework-within-a-framework, consisting of a couple of parts: There's a Form Builder, a Table Builder and a Notifications package and there's also an Admin Panel that combines them. Using the admin panel, you can create Resources that enable you to easily add CRUD pages with navigation, tables and forms to your app. It has all been expertly designed, and is very flexible to make your own changes if you need them. Check out their demo here: Filament Demo.

In this article, we'll take a first look at Filament and we'll build upon what we make now in future articles. Prepare for liftoff!

The app

In this series, I'm going meta.

No, not the social media/virtual reality company. Over the course of this mini-series, I'll write an app that will show information about its own deployment on Fly.io. It'll have a Machine model for every machine that's in your app, with a relation to a Region model that specifies where that machine is running. This will enable us to do something very cool: we can let the machines ping each other and see how fast they respond. In this article, we'll lay the foundations for that app.

Setting up Filament

So, create a new Laravel project and install the Filament admin panel with composer require filament/filament:"^2.0" . Now, run the migrations and create a user for yourself using php artisan make:filament-user .

Filament has been built to be an admin panel, but I'll color outside of the lines and use Filament for the whole app. I've heard that Filament v3 will support this idea even better, but for now it also works well. To make it feel like Filament is the only thing in our app, I removed the default welcome page and changed the Filament URL from /admin to the / home url. You can do this by adding FILAMENT_PATH="/" to your .env file. After that, just remove the default route from web.php and delete the resources/views/welcome.blade.php file.

Now, onto the Filament admin panel itself. I'll be using two models here: a Region model that has data about each region on Fly.io, and a Machine model that contains data about each machine where this app will be deployed. Machines will have a one-to-many relationship with Regions, so each Machine belongs to one Region. I'll use this setup later on to illustrate the latency between different regions, but that's for a different post 😉.

If you want to follow along, here are the models:

class Region extends Model
{
    protected $fillable = ['iata_code', 'name'];

    public function machines(): \Illuminate\Database\Eloquent\Relations\hasMany
    {
        return $this->hasMany(Machine::class);
    }
}

Both iata_code and name are normal strings.

class Machine extends Model
{
    protected $fillable = ['machine_id', 'region_id'];

    public function region(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(Region::class);
    }
}

Machine_id is a string and region_id is a foreign Id for the Region model.

Adding the RegionResource

Let's add a resource for our Region first, since that's the easiest. The model has only two properties: the iata_code is the airport code of that region (LAX for Los Angeles) and the name is well, the name of the region.

<aside class="right-sidenote"> Resources in Filament only describe how users interact with the Model, and how it should be presented, so make sure the Region model and database table already exist. </aside>

Resources in Filament are like superpowered classes that can handle all the CRUD operations using forms and tables. It's almost like magic! You can pick if they need to show separate pages for viewing and editing models or you can opt for a 'simple' single view and use modals for creating and updating. I'm a simple person, so I'll create a simple Resource for my Region model using php artisan make:filament-resource Region --simple . You're probably smarter than me so you would let Filament auto-generate the forms and tables as well. Install the doctrine/dbal package using composer require doctrine/dbal --dev and then add --generate to the command: php artisan make:filament-resource Region --simple --generate. Much easier!

Here's how it looks out of the box:

We actually have all we need already: we can do all the CRUD operations on our Region model, with validation on the form inputs! I'll change the label for the IATA code to have IATA in all caps by opening RegionResource and adding ->label("IATA Code") on the TextInput for the iata_code property. While we're at it we can also change the maxLength from 255 to 3. Here's how the form() looks now:

public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\TextInput::make('iata_code')
                    ->label("IATA Code")
                    ->required()
                    ->maxLength(3),
                Forms\Components\TextInput::make('name')
                    ->required()
                    ->maxLength(255),
            ]);
    }

And we can do the same thing for the column in the table:

public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('iata_code')
+                   ->label('IATA Code'),
                ...
    }

This is how almost all customization on tables and forms will be done: create the correct field and use the static methods to change it to whatever you need!

One last thing: I pulled a sneaky on ya! I used a different icon for the 'regions' navigation item. I wanted something more region-like than the default 'collection' icon, so I changed the $navigationIcon on the RegionResource class from heroicon-o-collection to heroicon-o-globe. It just makes more sense.

Adding the MachineResource

For the Machine resource, let's switch it up a bit and not use the 'simple' resource. This means we'll have different pages for index, edit, create and view operations. Run php artisan make:filament-resource Machine --generate et voilà: a MachineResource! For the Icon I'd suggest the heroicon-o-chip icon.

Let's now take a look at the MachineResource. Something special happened here, and I need you to be as excited about it as I am: In the form method, there is a TextInput just like with the RegionResource, but now there's also a Select. This lets you attach a related Region using the relationship on the Machine model. Filament will preload the Regions and let the user pick them from a list when creating a Machine. Pretty cool.

Let's make it even cooler: let's enable the user to filter the regions by typing in the field by adding ->searchable() and ->preload() on the Select field. The preload isn't necessary here, but it does enhance the experience by showing results before the user has typed and filtering faster. Let's see it in action!

Now, one final change to make before I let you return to watching cat videos: The MachineResource create form looks a bit weird, the input fields look like they've been thrown on the page. Let's group them together in a card! I'll also arrange both fields on one line, using ->columns(3) on the Card and ->columnSpan(2) on the Select field.

public static function form(Form $form): Form
{
    return $form
        ->schema([
+           Forms\Components\Card::make()
+               ->schema([
                    Forms\Components\TextInput::make('machine_id')
                        ->required()
                        ->maxLength(255),
                    Forms\Components\Select::make('region_id')
                        ->relationship('region', 'name')
                        ->required()
                        ->searchable()
                        ->preload()
+                       ->columnSpan(2),
+               ])
        ]);
}

Here's how it looks now:

Bear this in mind: we have only scratched the surface of what Filament can do, but we've already made a lot of progress: We already have CRUD operations for two models of our simple app, including form validation and relationships. On top of that we have authentication and navigation that's built-in. Not bad, right? Later on we'll customize the look and feel of our app, and after that we'll add the dashboard that displays the ping times between the different deployments of our app.

And just between me and you: They don't even know I'm writing this article. I just genuinely enjoyed using Filament and I couldn't wait to tell you about it. Better yet, Filament v3 is right around the corner (check out v3when.com!) so they'll probably have a lot more in store for us in the future. Keep it up guys!

Last updated 3 weeks ago.

driesvints, dprinzensteiner liked this article

2
Like this article? Let the author know and give them a clap!

Other articles you might like

Article Hero Image November 18th 2024

Laravel Custom Query Builders Over Scopes

Hello 👋 Alright, let's talk about Query Scopes. They're awesome, they make queries much easier to r...

Read article
Article Hero Image November 19th 2024

Access Laravel before and after running Pest tests

How to access the Laravel ecosystem by simulating the beforeAll and afterAll methods in a Pest test....

Read article
Article Hero Image November 11th 2024

🍣 Sushi — Your Eloquent model driver for other data sources

In Laravel projects, we usually store data in databases, create tables, and run migrations. But not...

Read article

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.