Come implementare il Multi-Tenancy in Laravel
La flessibilità del framework Laravel ci consente di implementare anche una architettura multi-tenancy.
La multi-tenancy è un'architettura software in cui una singola istanza di un'applicazione serve più applicazioni cliente.
Ogni tenant può essere considerato come un cliente separato con i propri dati isolati da altri tenant.
In questo post, esploreremo il concetto di multi-tenancy in Laravel, i suoi benefici e come implementarlo. Vedremo anche le configurazioni necessarie, esempi pratici di codice e i passaggi per garantire che l'applicazione multi-tenant funzioni senza problemi.
Estimated reading time: 5 minuti
Che cosa è il Multi-Tenancy?
La multi-tenancy è un'architettura che consente a una singola applicazione di ospitare più tenant (clienti) con i loro dati e configurazioni. I dati di ogni tenant sono isolati dagli altri, garantendo la riservatezza e la sicurezza dei dati. La multi-tenancy può essere implementata in vari modi, tra cui:
- Singolo database, Schema condiviso: tutti i tenant condividono lo stesso database e le stesse tabelle.
- Database singolo, Schemi separati: i tenant condividono lo stesso database ma hanno il proprio schema.
- Database multipli: ogni tenant ha il proprio database.
I vantaggi della multi-tenancy
- Scalabilità: più facile scalare l'applicazione per i nuovi tenant senza grandi cambiamenti.
- Efficienza dei costi: riduce i costi delle infrastrutture e della manutenzione condividendo le risorse tra i tenant.
- Manutenzione centralizzata: semplifica gli aggiornamenti e la manutenzione in quanto c'è solo un'istanza dell'applicazione.
- Esperienza utente migliorata: ambienti personalizzabili per diversi tenant.
Implementazione di Multi-Tenancy in Laravel
Sono stati sviluppati diversi tool per Laravel, per aiutare a implementare architetture multi-tenancy, come:
- hyn/multi-tenant: consente di gestire un’architettura software in cui un’unica istanza di un’applicazione serve più tenant (o account utente), garantendo la sicurezza e la riservatezza dei dati per ciascun gruppo di utenti. Questo tool è spesso utilizzato per fornire servizi SaaS (Software-as-a-Service).
- tenancy/tenancy: soluzione flessibile per il multi-tenancy in Laravel. Vediamo qui di seguito alcune caratteristiche:
- Automatic Tenancy: Invece di modificare la configurazione del tuo progetto, il pacchetto avvia automaticamente il multi-tenancy in background. Cambia le connessioni al database, separa le cache, aggiunge prefissi ai filesystem e altro ancora;
- Separazione automatica dei dati: Il pacchetto rende automaticamente tenant-aware: database, cache, filesystem, code e store Redis. Non devi modificare nulla se hai già scritto il tuo progetto;
- Integrazione con altri pacchetti: Poiché la modalità automatica cambia la connessione al database predefinita, molti altri pacchetti utilizzeranno questa connessione. Ad esempio, puoi utilizzare Laravel Nova all’interno dell’applicazione tenant per gestire le risorse del tenant;
- Architettura basata su eventi: La logica di avvio del multi-tenancy, la logica post-creazione del tenant e altre operazioni avvengono grazie agli eventi. Puoi personalizzare ogni aspetto;
- Multi-database tenancy: Se non vuoi utilizzare l’approccio database-per-tenant, il pacchetto offre modelli per limitare i modelli al tenant corrente, anche per modelli non direttamente correlati al tenant;
In questo articolo useremo il tool tenancy/tenancy, che fornisce una solida base per la multi-tenancy in Laravel. Vediamo quindi passo per passo come implementare la multi-tenancy in Laravel.
Passaggio 1: installare il pacchetto
Per prima cosa, installiamo il pacchetto tenancy/tenancy con il composer:
composer require tenancy/tenancy
Passaggio 2: pubblicare la configurazione
Procediamo ora a pubblicare i file di configurazione del pacchetto:
php artisan vendor:publish --tag=tenancy
Passaggio 3: Impostare il Tenancy
Procediamo ora a configurare il file tenancy.php, che si trova nella directory config, per soddisfare le esigenze applicative.
Quindi seguito ci sono alcuni parametri:
- storage_driver, storage: puoi configurare il driver per lo storage dei tenant. Ad esempio, puoi scegliere tra Redis o un database. Leggi di più sulla pagina dei driver di storage.
- tenant_route_namespace: Imposta il namespace del controller utilizzato per le rotte in routes/tenant.php.
- exempt_domains: Se un hostname presente in questo array viene visitato, le rotte in tenant.php non verranno registrate, consentendoti di utilizzare le stesse rotte presenti in quel file.
- database: Imposta la connessione al database per i dati del tenant.
- redis: Configura la connessione Redis per i dati del tenant.
- cache: Sostituisce l’istanza di CacheManager per supportare il multi-tenancy.
- filesystem: Configura il percorso di archiviazione dei file per i tenant.
Per una guida completa leggi la documentazione.
Passaggio 4: creare il modello di Tenant
Creare un modello di Tenant per rappresentare ogni tenant nella tua applicazione:
php artisan make:model Tenant -m
Nel file di migrazione, definire la struttura della tabella tenants:
Schema::create('tenants', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('domain')->unique();
$table->timestamps();
});
Passaggio 5: Identificazione del tenant
Identificare il tenant in base al dominio o al sottodominio. Aggiorniamo quindi il modello del Tenant per includere la logica di identificazione del tenant:
namespace AppModels;
use IlluminateDatabaseEloquentModel;
use TenancyIdentificationContractsTenant as TenantContract;
use TenancyAffectsConnectionsContractsProvidesDatabase;
class Tenant extends Model implements TenantContract, ProvidesDatabase
{
protected $fillable = ;
public function getTenantKey(): string
{
return 'domain';
}
public function getConnectionName(): string
{
return 'tenant';
}
public function configureDatabase($event): void
{
$event->useConnection('tenant', );
}
}
Quindi i metodi sono tre, getTenantKey per identificare il dominio, getConnectionName per identificare la connessione e configureDatabase per impostare la connessione al DB corretto.
Passaggio 6: Configurare il Middleware
Creiamo il middleware che si occuperà di cambiate la connessione del database in base al tenant:
php artisan make:middleware TenantMiddleware
Nel middleware, identifichiamo il tenant e impostiamo la connessione al database:
namespace AppHttpMiddleware;
use Closure;
use TenancyIdentificationContractsTenant;
class TenantMiddleware
{
public function handle($request, Closure $next)
{
$hostname = $request->getHost();
$tenant = Tenant::where('domain', $hostname)->first();
if ($tenant) {
tenant($tenant);
}
return $next($request);
}
}
Quindi registriamo il middleware TenantMiddleware in app/Http/Kernel.php:
protected $middlewareGroups = ,
];
Passaggio 7: Migration dei Tenant
Creare migrazioni specifiche per tenant specificando la connessione del tenant:
php artisan make:migration create_posts_table --create=posts --path=database/migrations/tenant
Nel file di migrazione, definire la struttura della tabella del tenant:
Schema::connection('tenant')->create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
Passaggio 8: Migrazioni del Tenant
Creare un comando per eseguire migrazioni specifiche del tenant:
php artisan make:command MigrateTenants
Nel file di comando, eseguire le migrazioni per ogni tenant:
namespace AppConsoleCommands;
use IlluminateConsoleCommand;
use AppModelsTenant;
class MigrateTenants extends Command
{
protected $signature = 'migrate:tenants';
protected $description = 'Run migrations for all tenants';
public function handle()
{
Tenant::all()->each(function (Tenant $tenant) {
tenant($tenant);
$this->call('migrate', );
});
$this->info('Tenant migrations completed successfully.');
}
}
Passaggio 9: Seed del Tenant
Creare un seeder per seminare i dati specifici del tenant:
php artisan make:seeder TenantSeeder
Nel seminatore, definire i dati da seminare:
namespace DatabaseSeeders;
use IlluminateDatabaseSeeder;
use AppModelsTenant;
class TenantSeeder extends Seeder
{
public function run()
{
Tenant::create();
Tenant::create();
}
}
Esegui il sider:
php artisan db:seed --class=TenantSeeder
Scenari pratici
Applicazioni SaaS
La multi-tenancy è ideale per le applicazioni SaaS in cui più clienti (tenants) devono utilizzare la stessa applicazione mantenendo i loro dati separati.
Grandi organizzazioni
Le organizzazioni con più reparti possono utilizzare multi-tenancy per gestire i dati dipartimentali separatamente all'interno della stessa applicazione.
Hosting gestito
I provider di hosting possono utilizzare la multi-tenancy per offrire servizi gestiti a più clienti con ambienti isolati.
Ercole Palmeri
Ercole Palmeri
#laravel #PHPTutorial #SoftwareEngineering #Tutorial
https://bloginnovazione.it/multi-tenancy/49605/
Commenti
Posta un commento