If you want to use the Filament admin panel, here's the code of the User
Model configured for it:
app/Models/User.php:
namespace App\Models; use Filament\Models\Contracts\FilamentUser;use Filament\Panel;use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements FilamentUser{ // ... public function canAccessPanel(Panel $panel): bool { return str_ends_with($this->email, '@yourdomain.com') && $this->hasVerifiedEmail(); }}
Three questions:
- What does it mean
implements FilamentUser
? How is it different fromextends
? - Why is that
FilamentUser
in theContracts
namespace? What are "contracts"? - What happens if we don't define the
canAccessPanel()
method exactly as described?
Let's answer those, one by one.
Implements vs Extends: Interfaces
The syntax extends XYZ
we had seen earlier means that our new class inherits all the same behavior of that parent class, with the ability to override something on top.
But what if we don't have a specific parent class but instead want to define a set of rules that all the "children" classes should follow?
Meet interfaces.
They are not classes. They don't have any implementations of properties/methods, but they have their definitions inside.
So, FilamentUser
is an interface:
vendor/filament/filament/src/Models/Contracts/FilamentUser.php
namespace Filament\Models\Contracts; use Filament\Panel; interface FilamentUser{ public function canAccessPanel(Panel $panel): bool;}
That's it, a short PHP file, right? So what is its purpose?
As I mentioned above, it defines the rules for all the classes that want to follow them.
In human language, if you want to use Filament and want your User model to have the ability to access the admin panel, you need to define the canAccessPanel()
method in your User class: that's the rule of the interface.
As you can see, the interface doesn't have the "body" of that method, only the definition:
- Method name
- Method "visibility" (public/private/protected)
- Method parameters
- Method return type
Why Interface?
Maybe some of you may ask: "Why not create a class and use extends here"?
The point is that Filament, as a framework, doesn't actually "know" what should be inside of that method. Framework creators can't define the panel access for you: only you, as a framework user, can define who can access the panel in your case.
So, Filament's role is to define the rules, and your role is to implement them.
Why "Contract"?
Another question: why is it called a "contract"?
The word "contract" is a synonym for the "interface". It's just often used more broadly in many programming languages. If you think about it, it's a more human-language description of a "set of rules". By using Filament, you "sign a virtual contract" to follow its rules in your classes.
The word "interface" is a PHP language word for "contracts". But this word is also used in other languages, so if you talk on any dev forums or communities, they would likely understand you if you use either of those terms.
And it's not just a Filament thing: Laravel framework also uses Contracts as a namespace in Illuminate/Contracts, where many interfaces are defined inside.
What if we don't implement the method?
Finally, what happens if we don't define that canAccessPanel()
in our User model?
We will get a PHP error:
Even PhpStorm IDE underlines the class immediately if you use implement FilamentUser
but don't actually implement its method(s):
In other words, without this method, Filament wouldn't work at all. That's why it's a strict rule to implement it. That's the whole point of interfaces: to give us strict rules.
Only public visability!
It's called a method signature.
Why do we sometimes prefer an abstract class to an interface and vice versa?
Method signatures in Interface do not contain logic. That is, by using interfaces in class composition/aggregation, we abstract away from the details.
Abstract classes, in addition to method signatures, usually contain some generalizing logic for the subclases.
Q) can a person have two implanments in a class for example
class User extends Authenticatable implements FilamentUser, HasMenu
Thanks
Yes, in php you can implements many interfaces. Interfaces can extends many interfaces, but class can exteends one class.