Filament 3 Multi-Tenancy: Validation - Unique Value Per Tenant

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.

unique column per 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.

avatar

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) ),

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 55 courses (987 lessons, total 46 h 42 min)
  • 77 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials