Criar uma aplicação SaaS com múltiplos locatários (multi-tenancy) é um desafio comum — e também uma grande oportunidade. Mas quando combinamos o poder do Laravel, a produtividade do FilamentPHP e uma arquitetura multi-tenant bem planejada, temos uma base sólida para construir projetos escaláveis, seguros e modernos.
Neste artigo, você vai aprender como integrar o FilamentPHP com multi-tenancy em Laravel, criando a base ideal para uma aplicação SaaS. Vamos abordar conceitos essenciais, ferramentas recomendadas e boas práticas de implementação.
O que é Multi-Tenancy e por que isso importa?
Multi-tenancy é uma arquitetura onde uma única aplicação atende múltiplos clientes (ou empresas), isolando dados e recursos entre eles. Cada cliente é chamado de “tenant” (locatário), e pode ter seus próprios usuários, dados, configurações e até customizações específicas.
Tipos de multi-tenancy:
- Banco de dados compartilhado com segregação por coluna: (ex: tenant_id)
- Banco de dados por tenant
- Schema por tenant
Neste artigo, vamos focar no modelo mais comum e simples: coluna tenant_id em tabelas compartilhadas.
1. Configurando o ambiente com Laravel e FilamentPHP
Instalando o Laravel e o FilamentPHP
composer create-project laravel/laravel meu-saas
cd meu-saas
composer require filament/filament
php artisan filament:install
Crie um super usuário para acessar o painel Filament:
php artisan make:filament-user
Acesse /admin para validar a instalação.
2. Adicionando suporte a Multi-Tenancy
Instalando um pacote de multi-tenancy
A opção mais direta é usar o pacote stancl/tenancy:
composer require stancl/tenancy
php artisan tenancy:install
php artisan migrate
Este pacote suporta múltiplas abordagens, inclusive subdomínios e customização por tenant. Mas você também pode implementar multi-tenancy manualmente, especialmente no modelo com tenant_id.
3. Estruturando tabelas com tenant_id
Vamos assumir que cada usuário pertence a uma empresa (tenant), e os dados são segmentados por tenant_id.
Criação das tabelas
php artisan make:model Empresa -m
php artisan make:model Produto -m
Exemplo de migration da tabela produtos:
Schema::create('produtos', function (Blueprint $table) {
$table->id();
$table->foreignId('empresa_id')->constrained()->onDelete('cascade');
$table->string('nome');
$table->decimal('preco', 8, 2);
$table->timestamps();
});
No model:
class Produto extends Model
{
protected $fillable = ['empresa_id', 'nome', 'preco'];
public function empresa()
{
return $this->belongsTo(Empresa::class);
}
}
4. Integrando com o FilamentPHP
Filtrando dados automaticamente por empresa_id
Você pode criar um global scope ou aplicar a filtragem no Resource:
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()->where('empresa_id', auth()->user()->empresa_id);
}
Ajustando o Formulário de Criação
No ProdutoResource, adicione automaticamente o empresa_id ao salvar:
protected function mutateFormDataBeforeCreate(array $data): array
{
$data['empresa_id'] = auth()->user()->empresa_id;
return $data;
}
Repita a lógica para o método de update, se necessário.
5. Controle de acesso por tenant
Criando Policies
Crie policies com validação baseada no empresa_id:
php artisan make:policy ProdutoPolicy --model=Produto
Exemplo:
public function update(User $user, Produto $produto)
{
return $user->empresa_id === $produto->empresa_id;
}
6. Boas práticas e desafios comuns
- Nunca confie apenas no front-end para ocultar dados. Sempre filtre pelo empresa_id.
- Use database transactions para manter integridade entre tenants.
- Evite hardcode de tenant em rotas ou controllers.
- Para escala futura, considere arquiteturas com banco por tenant.
Conclusão
Integrar o FilamentPHP com multi-tenancy em Laravel é uma solução poderosa para construir aplicações SaaS modernas, com interface elegante, produtividade de alto nível e segurança por isolamento de dados.
Seja para MVPs ou plataformas robustas, essa combinação te dá velocidade e flexibilidade para entregar valor rapidamente aos seus clientes.