Come realizzare un’applicazione Laravel Multi-tenant — Parte 1

Francesco Lettera
5 min readJul 3, 2018

--

Parte 0 | Parte 1 | Parte 2 | Parte 3 | Parte 4 | Parte 5 | Parte 6

Questa è la traduzione della serie Full-featured multi-tenant Laravel app from scratch di Ashok Gelal

In questa parte ci occuperemo dei seguenti task:

✅ Creare un progetto

✅ Impostare il db e l’utente

✅ Installare e configurare il package multi-tenant

✅ Aggiungere un comando artisan per creare un tenant

✅ Aggiungere un comando artisan per cancellare un tenant

1. Creare un nuovo progetto Laravel

Iniziamo creando un nuovo progetto Laravel. Semplicemente:

$ laravel new townhouse

2. Impostare un database

Così come la maggior parte delle web app, townhouse ha bisogno di un database e di un database user. Ma, a differenza di molte altre app questo database user sarà un po’ differente. Perché la nostra app creerà 1 database per ogni tenant, il nostro database user ha bisogno di speciali privilegi per fare questo.

N.b. I seguenti step per creare un database ed un utente sono applicabili solo ad utenti MacOS + SequelPro, ma dovrebbe essere semplice scegliere qualsiasi altro OS o database.

Se non ce l’hai pronto, scarica e installa SequelPro. Connettiti come root al tuo server locale MySQL e crea un nuovo database chiamato townhousedb.

Crea un nuovo utente, townhouseadmin, e imposta la password come secret. Vai nel tab dei Global Privileges e clicca il bottone Check all. Vai nel tab Schema Privileges e seleziona townhousedb dalla lista degli schema. Seleziona Available Privileges con il comando CDM + A e clicca sul bottone per assegnare tutti i privilegi. Dunque, clicca su Apply.

Adesso, informiamo la nostra app che è presente una connessione al db. Potresti aver lasciato il nome di default della connessione db come — mysql — ma siccome utilizziamo database multipli, chiamarlo semplicemente mysql potrebbe creare qualche confusione in futuro. Dunque, lo chiameremo system.

Apri config/database.php e cambia il nome della seconda connessione da mysql a system.

Adesso apri il tuo file .env e fai il seguente cambiamento:

DB_CONNECTION=system
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=townhousedb
DB_USERNAME=townhouseadmin
DB_PASSWORD=secret

E’ tutto quello di cui abbiamo bisogno per impostare un db. Il package multi-tenant si preoccuperà del resto quando dovremo impostare un database per ogni nuovo tenant.

3. Installa e configura il package multi-tenant

Prima di tutto, vai a leggere la documentazione sul package che utilizzeremo — Laravel Tenancy. E’ normale se non comprendi ogni cosa in questo momento. Acquista familiarità con la documentazione, poi aggiungi il package:

composer require hyn/multi-tenant

Siccome stiamo utilizzando MySQL, abbiamo bisogno di limitare la lunghezza UUID generata dal package multi-tenant sotto i 32 caratteri e questo può essere impostato utilizzando una variabile d’ambiente LIMIT_UUID_LENGTH_32. Impostala a true nel tuo file .env:

LIMIT_UUID_LENGTH_32=true

Ancora una cosa prima di lavorare alla nostra app multi-tenant (MTA) — ci piacerebbe che ogni tenant abbia i suoi utenti e abbiamo bisogno di una tabella per lo storing di questi utenti. Come saprai, Laravel di default parte con due file di migrazione:

2014_10_12_000000_create_users_table.php e 2014_10_12_100000_create_password_resets_table.php

Se vuoi che la nostra MTA faccia la migrazione con queste due tabelle per ogni tenant, allora hai bisogno di spostare questi due file in una cartella speciale: database/migrations/tenant

Il package multi-tenant si preoccuperà di lanciare la migration in questa cartella per ogni nuovo sito tenant. Facile!

Infine, è il momento di convertire la nostra app in MTA. Utilizzeremo uno dei comandi built-in del multi-tenant per fare questo:

php artisan tenancy:install

Questo comando migrerà tutte le tabelle di cui hai bisogno per realizzare la tua app MTA.

Se dai un’occhiata al tuo database townhousedb, noterai una serie di tabelle — customers, hostnames, migrations, e websites. Inoltre noterai che non ci sono le tabelle users o password_resets.

4. Aggiungi un comando artisa per creare un tenant

Invece di spendere il nostro prezioso tempo a lavorare sulla UI per un superadmin deputato a creare un nuovo tenant, possiamo semplicemente creare un comando artisan. Aggiungiamone uno:

php artisan make:command CreateTenant

E poi lasciamo che funzioni:

La classe si spiega da sola — ci accertiamo che un tenant non esista già controllando il nome e/o l’email. Poi creiamo un cliente (tenant), un sito web e un hostname per il sito web. Poi creiamo un admin con una password generata randomicamente e quindi eventualmente stampiamo tutte le info di cui abbiamo bisogno per il nuovo tenant e l’admin inizierà quindi ad utilizzare l’app.

Ti prego di osservare che non abbiamo impostato alcun permesso per questo nuovo utente. Lo faremo poi.

C’è ancora un altro step da valutare prima di creare un nuovo tenant — impostare un URL per il FQDN dell’hostname (vedi la linea #64). Potremmo lavorarci su, ma l’hostname sarà differente sul tuo environment dev e production. Ecco perché lo imposteremo con una combinazione di config + env:

// add a new new key in config/app.php:                       ‘url_base’ => env(‘APP_URL_BASE’, ‘http://localhost'),// modify your .env file:                       APP_URL_BASE=townhouse.dev                       APP_URL=http://${APP_URL_BASE}

Adesso creiamo un nuovo tenant:

php artisan tenant:create boise boise@example.com

Boom! Dovresti vedere qualcosa di simile:

Non esagerare con una interfaccia complessa per un compito semplice

5. Aggiungi un comando artisan per cancellare un tenant

Avrai bisogno di cancellare un tenant prima o poi. Forse non per una live app, ma un modo per cancellare un tenant sarà un’attività utile durante lo sviluppo a meno che tu non voglia cancellare tutti i database, utenti e cartelle manualmente dopo ogni test.

Quindi creiamo un nuovo comando artisan per fare questo:

php artisan make:command DeleteTenant

E quindi:

Ti prego di osservare che permettiamo il running di questo comando solo in locale. Non vuoi accidentalmente cancellare un tenant nel tuo server di produzione.

Il comando qui sopra cancella la maggior parte degli artefatti generati dal package multi-tenant ad eccezione del — database tenant, utente tenant, e le cartelle storage del tenant. Per cancellare il resto, dobbiamo accendere alcune configurazioni nel file di configurazione tenancy.php che non abbiamo ancora pubblicato.

Facciamolo:

php artisan vendor:publish

Poi selezioniamo:

Provider: Hyn\Tenancy\Providers\Tenants\ConfigurationProvider

Questo pubblicherà un file config/tenancy.php. Editiamolo con due cambiamenti:

...'auto-delete-tenant-directory' => env('AUTO_DELETE_TENANT_DIRECTORY', false),...'auto-delete-tenant-database' => env('AUTO_DELETE_TENANT_DATABASE', false),...

E impostiamo queste chiavi nel file .env:

AUTO_DELETE_TENANT_DIRECTORY=true                       AUTO_DELETE_TENANT_DATABASE=true

Adesso siamo pronti per cancellare il tenant che abbiamo creato poco fa:

php artisan tenant:delete boise

Tutti gli artefatti relativi al tenant saranno cancellati!

Sei ancora con me? Bene! Abbiamo fatto un sacco di cose per preparare il terreno. Nel prossimo post, vedremo come applicare regole e permessi per la nostra app così come inseriremo nel db un po’ di dati per ogni tenant.

--

--