Filament 3 has a multi-tenancy feature. In this tutorial, let's make a validation rule with a unique field value for the current tenant. As with everything with Laravel, there is more than one way to do it, so we will see how to achieve it in three ways.
In this example, our tenant is a Company
Model and is set in the Panel Provider:
app/Providers/Filament/AdminPanelProvider.php:
use App\Models\Company; class AdminPanelProvider extends PanelProvider{ public function panel(Panel $panel): Panel { return $panel ->default() ->tenant(Company::class) // ... }}
The Filament Resource is a CategoryResource
with just one name
field, which needs to be unique just for an active tenant.
Method 1. Filament Custom Callback
For the first method, we will use a custom validation rule and pass a closure to it.
Forms\Components\TextInput::make('name') ->rules([ function () { return function (string $attribute, $value, Closure $fail) { if (filament()->getTenant()->categories->contains('name', $value)) { $fail('The :attribute must be unique per tenant.'); } }; } ]) ->required() ->maxLength(255),
In this callback, we check if, in the tenants categories
relation, there is a $value
in the name
DB field. If the check is true, we show the validation error.
Method 2. Laravel Validation Rule::unique()
For the second method, we will use a Laravel validation rule unique, which needs to be added to the rules
method.
use Illuminate\Validation\Rule; Forms\Components\TextInput::make('name') ->rules(Rule::unique('categories', 'name')->where('company_id', filament()->getTenant()->id)) ->required() ->maxLength(255),
For the Rule
, we are setting the relation name and field name and adding where to check the current tenant.
Method 3. Filament unique()
The last third method will use the Filament unique rule.
Forms\Components\TextInput::make('name') ->unique('categories', 'name', null, 'id', function($rule){ return $rule->where('company_id', filament()->getTenant()->id); }) ->required() ->maxLength(255),
Similar to the second method, we set the relation name with the field name and add where to check the current tenant.
So, which method do you prefer?
If you want more Filament examples, you can find more real-life projects on our FilamentExamples.com.
Another way for doing it if using simple tenancy: Forms\Components\TextInput::make('invoice_number') ->label(Invoice Number') ->required() ->unique( 'orders', 'invoice_number', ignoreRecord: true, modifyRuleUsing: fn($rule) => $rule->where('team_id', auth()->user()>team_id) ),