A criação de um SaaS multiempresa (multi-tenancy) com Laravel pode parecer um desafio, mas o framework oferece diversas abordagens para implementação. Neste artigo, vamos explorar o conceito de multi-tenancy, as principais estratégias de implementação e como estruturar um sistema eficiente e seguro.
O Que é Multi Tenancy?
Multi-tenancy (ou multiempresa) é um modelo de arquitetura onde um único aplicativo atende a várias organizações (tenants), garantindo isolamento adequado dos dados. Isso permite que um SaaS sirva múltiplos clientes sem precisar manter várias instâncias do mesmo sistema.
Estratégias de Multi Tenancy no Laravel
O Laravel suporta diferentes abordagens para multi-tenancy. As principais são:
- Banco de Dados Compartilhado (Single Database, Scoped by Tenant)
- Todos os tenants compartilham o mesmo banco de dados.
- As tabelas incluem uma coluna
company_id
para separar os dados. - Recomendado para SaaS que não exigem alto isolamento de dados.
- Banco de Dados Separado por Cliente (Multiple Databases)
- Cada tenant tem seu próprio banco de dados.
- O Laravel muda dinamicamente a conexão do banco de acordo com o tenant.
- Oferece maior isolamento, mas pode ser mais complexo de gerenciar.
- Schema Separado (Multiple Schemas in a Single Database)
- Cada tenant tem seu próprio esquema dentro do mesmo banco de dados.
- Um bom equilíbrio entre isolamento e eficiência de recursos.
Implementando Multi Tenancy no Laravel
1. Estruturando o Banco de Dados
Se optar pelo banco de dados compartilhado, inclua uma coluna company_id
em todas as tabelas relevantes:
Schema::table('users', function (Blueprint $table) {
$table->unsignedBigInteger('company_id');
$table->foreign('company_id')->references('id')->on('companies');
});
2. Configurando o Middleware para Identificar o Tenant
Podemos criar um middleware para identificar o tenant a partir do subdomínio ou cabeçalho:
namespace App\Http\Middleware;
use Closure;
use App\Models\Company;
class IdentifyTenant
{
public function handle($request, Closure $next)
{
$host = $request->getHost();
$company = Company::where('domain', $host)->firstOrFail();
app()->instance('tenant', $company);
return $next($request);
}
}
Adicione esse middleware no Kernel.php:
protected $middleware = [
\App\Http\Middleware\IdentifyTenant::class,
];
3. Aplicando Filtro Global para Restringir os Dados
Podemos usar Global Scopes para restringir automaticamente os dados por tenant:
namespace App\Models\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class TenantScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
if ($tenant = app('tenant')) {
$builder->where('company_id', $tenant->id);
}
}
}
Adicione esse escopo ao seu modelo:
use App\Models\Scopes\TenantScope;
protected static function boot()
{
parent::boot();
static::addGlobalScope(new TenantScope);
}
Agora, todas as consultas serão automaticamente filtradas pelo company_id
!
4. Configurando Conexões Dinâmicas para Múltiplos Bancos
Se cada tenant tiver seu próprio banco, podemos configurar a conexão dinamicamente:
DB::purge('tenant');
config(['database.connections.tenant' => [
'driver' => 'mysql',
'host' => $tenant->db_host,
'database' => $tenant->db_name,
'username' => $tenant->db_user,
'password' => $tenant->db_password,
]]);
DB::reconnect('tenant');
E então, basta definir a conexão nos modelos:
class User extends Model
{
protected $connection = 'tenant';
}
5. Utilizando Pacotes para Facilitar a Implementação
Se preferir uma solução pronta, o pacote Spatie Laravel Multitenancy simplifica a configuração:
composer require spatie/laravel-multitenancy
Ele permite configurar a identificação de tenants e mudança dinâmica de banco de dados com poucas linhas de código.
Conclusão
Implementar multi-tenancy no Laravel exige planejamento, mas o framework oferece diversas ferramentas para tornar essa tarefa mais simples. Seja optando por um banco compartilhado, múltiplos esquemas ou bancos separados, a escolha depende da complexidade e necessidades do seu SaaS.
Se estiver construindo um SaaS multiempresa, considere o isolamento de dados, segurança e escalabilidade desde o início para evitar problemas futuros!
Gostou do artigo? Compartilhe com sua equipe e comece a construir seu SaaS multi-tenancy com Laravel! 🚀