Une extension pour utiliser Laravel dans un environnement multi-domaine
Ce package permet à une seule installation de Laravel de fonctionner avec plusieurs domaines HTTP.
Il existe de nombreux cas dans lesquels différents clients utilisent la même application en termes de code mais pas en termes de base de données, de stockage et de configuration.
Ce package offre un moyen très simple d'obtenir un fichier env spécifique, un chemin de stockage spécifique et une base de données spécifique pour chacun de ces clients.
Laravel | Multidomaine |
---|---|
11.x | 11.x |
10.x | 10.x |
9.x | 5.x |
8.x | 4.x |
7.x | 3.x |
6.x | 2.x |
5.8.x | 1.4.x |
5.7.x | 1.3.x |
5.6.x | 1.2.x |
5.5.x | 1.1.x |
Sorties v1.1.x :
À ce jour, les versions v1.1.6+, v1.2.x, v1.3.x, v1.4.x, v2.x et v3.x sont fonctionnellement équivalentes. Les versions ont été séparées afin d'exécuter des tests d'intégration avec la version correspondante du framework Laravel.
Cependant, avec la sortie de Laravel 8, les versions v1.1.14, v1.2.8, v1.3.8 et v1.4.8 sont les dernières versions incluant de nouvelles fonctionnalités pour les versions correspondantes de Laravel 5.x (la prise en charge des corrections de bugs est toujours active pour ces versions) . MISE À JOUR du 13/02/2021 : certaines dernières fonctionnalités des versions v1.1+ sont toujours en cours :)
La v1.0 nécessite Laravel 5.1, 5.2, 5.3 et 5.4 (plus maintenu et non testé par rapport à laravel 5.4, cependant l'utilisation du package est la même que pour la 1.1)
2023-02-20 MISE À JOUR : À partir de Laravel 10.x, les versions du package suivent la même numérotation.
Ajoutez gecche/laravel-multidomain comme exigence à composer.json :
{
"require" : {
"gecche/laravel-multidomain" : "11.*"
}
}
Mettez à jour vos packages avec composer update ou installez avec composer install.
Vous pouvez également ajouter le package en utilisant composer require gecche/laravel-multidomain
et spécifier ultérieurement la version souhaitée.
Ce package doit remplacer la détection du domaine HTTP dans un ensemble minimal de fonctions principales de Laravel au tout début du processus d'amorçage afin d'obtenir le fichier d'environnement spécifique. Ce package nécessite donc quelques étapes de configuration supplémentaires que la plupart des packages Laravel.
Étapes d'installation :
bootstrap/app.php
. //use Illuminate F oundation A pplication
use Gecche Multidomain Foundation Application
QueueServiceProvider
par celui étendu dans le fichier config/app.php
comme suit : ' providers ' => Illuminate Support ServiceProvider:: defaultProviders ()-> merge ([
// Package Service Providers . . .
])-> replace ([
Illuminate Queue QueueServiceProvider::class => Gecche Multidomain Queue QueueServiceProvider::class,
])-> merge ([
// Added Service Providers ( Do not remove this line ) . . .
])-> toArray (),
Veuillez noter que si vous avez modifié le fichier config/app.php
pour d'autres raisons, il existe probablement déjà l'entrée providers
ci-dessus dans ce fichier et la seule ligne importante est celle qui remplace QueueServiceProvider
.
php artisan vendor:publish
(Ce package utilise la fonctionnalité de découverte.)
En suivant les étapes ci-dessus, votre application connaîtra le domaine HTTP dans lequel il s'exécute, à la fois pour les requêtes HTTP et CLI, y compris la prise en charge des files d'attente.
REMARQUE : dans Laravel 11, l'installation est plus simple qu'avant : si vous utilisez une version précédente de Laravel, veuillez vérifier dans la documentation les étapes d'installation.
Le package est compatible avec Horizon, grâce aux contributions de la communauté. Si vous devez utiliser ce package avec Horizon, vous devez suivre deux autres étapes d'installation :
Installez Laravel Horizon comme d'habitude
Remplacez l'importation Laravel Horizon tout en haut du fichier app/Providers/HorizonServiceProvider.php.
//use Laravel H orizon H orizonApplicationServiceProvider ;
use Gecche Multidomain Horizon HorizonApplicationServiceProvider ;
Ce package ajoute trois commandes pour gérer les domaines HTTP de votre application :
domain.add
La commande principale est la domain:add
qui prend en argument le nom du domaine HTTP à ajouter à l'application. Supposons que nous ayons deux domaines, site1.com
et site2.com
, partageant le même code.
Nous faisons simplement :
php artisan domain:add site1.com
et
php artisan domain:add site2.com
Ces commandes créent deux nouveaux fichiers d'environnement, .env.site1.com
et .env.site2.com
, dans lesquels vous pouvez mettre la configuration spécifique de chaque site (par exemple, configuration des bases de données, configuration du cache et autres configurations, comme on le trouve habituellement dans un environnement). déposer).
La commande ajoute également une entrée dans la clé domains
dans le fichier config/domains.php
.
De plus, deux nouveaux dossiers sont créés, storage/site1_com/
et storage/site2_com/
. Ils ont la même structure de dossiers que le stockage principal.
Les personnalisations de cette sous-structure storage
doivent correspondre aux valeurs du fichier config/domain.php
.
domain.remove
La commande domain:remove
supprime le domaine HTTP spécifié de l'application en supprimant son fichier d'environnement. Par exemple :
php artisan domain:remove site2.com
L'ajout de l'option force
supprimera le dossier de stockage du domaine.
La commande supprime également l'entrée appropriée de la clé domains
dans le fichier config/domains.php
.
domain.update_env
La commande domain:update_env
transmet un tableau de données codé en json pour mettre à jour un ou tous les fichiers d'environnement. Ces valeurs seront ajoutées à la fin du .env approprié.
Mettez à jour un fichier d'environnement de domaine unique en ajoutant l'argument domain
.
Lorsque l'argument domain
est absent, la commande met à jour tous les fichiers d'environnement, y compris celui standard .env
.
La liste des domaines à mettre à jour est conservée dans le fichier de configuration domain.php
.
Par exemple :
php artisan domain:update_env --domain_values='{"TOM_DRIVER":"TOMMY"}'
ajoutera la ligne TOM_DRIVER=TOMMY
à tous les fichiers d'environnement de domaine.
domain.list
La commande domain:list
répertorie les domaines actuellement installés, avec leur fichier .env et leur chemin de stockage.
La liste est conservée dans la clé domains
du fichier de configuration config/domain.php
.
Cette liste est automatiquement mise à jour à chaque exécution des commandes domain:add
et domain:remove
.
config:cache
La commande config:cache artisan peut être utilisée avec ce package de la même manière que n'importe quelle autre commande artisan.
Notez que cette commande générera un fichier config.php pour chaque domaine sous lequel la commande a été exécutée. C'est à dire la commande
php artisan config:cache --domain=site2.com
générera le fichier
config-site2_com.php
Au moment de l'exécution, le domaine HTTP actuel est conservé dans le conteneur laravel et est accessible via sa méthode domain()
ajoutée par ce package.
Une méthode domainList()
est disponible. Il renvoie un tableau associatif contenant les informations sur les domaines installés, similaire à la commande domain.list
ci-dessus.
Par exemple
[
site1.com => [
'storage_path' => <LARAVEL-STORAGE-PATH>/site1_com,
'env' => '.env.site1.com'
]
]
Pour chaque requête HTTP reçue par l'application, le fichier d'environnement spécifique est chargé et le dossier de stockage spécifique est utilisé.
Si aucun fichier d'environnement et/ou dossier de stockage spécifique n'est trouvé, le fichier standard est utilisé.
La détection du bon domaine HTTP se fait à l'aide de la variable PHP $_SERVER['SERVER_NAME']
.
REMARQUE IMPORTANTE : dans certains environnements d'exécution, $_SERVER['SERVER_NAME'] n'est pas instancié, ce package ne fonctionne donc pas correctement tant que vous n'avez pas personnalisé la détection des domaines HTTP comme décrit ci-dessous.
À partir de la version 1.1.15, la détection des domaines HTTP peut être personnalisée en passant un Closure
comme entrée domain_detection_function_web
du nouvel argument domainParams
du constructeur de Application
. Dans l'exemple suivant, la détection de domaine HTTP s'appuie sur $_SERVER['HTTP_HOST']
au lieu de $_SERVER['SERVER_NAME']
.
//use Illuminate F oundation A pplication ;
use Gecche Multidomain Foundation Application ;
use Illuminate Foundation Configuration Exceptions ;
use Illuminate Foundation Configuration Middleware ;
$ environmentPath = null ;
$ domainParams = [
' domain_detection_function_web ' => function () {
return Illuminate Support Arr:: get ( $ _SERVER , ' HTTP_HOST ' );
}
];
return Application:: configure (basePath: dirname ( __DIR__ ),
environmentPath: $ environmentPath ,
domainParams: $ domainParams )
-> withRouting (
web: __DIR__ . ' /../routes/web.php ' ,
commands: __DIR__ . ' /../routes/console.php ' ,
health: ' /up ' ,
)
-> withMiddleware ( function ( Middleware $ middleware ) {
//
})
-> withExceptions ( function ( Exceptions $ exceptions ) {
//
})-> create ();
Afin de distinguer les domaines, chaque commande artisanale accepte une nouvelle option : domain
. Par exemple :
php artisan list --domain=site1.com
La commande utilisera les paramètres de domaine correspondants.
Les commandes artisanales queue:work
et queue:listen
ont été mises à jour pour accepter une nouvelle option domain
.
php artisan queue:work --domain=site1.com
Comme d'habitude, la commande ci-dessus utilisera les paramètres de domaine correspondants.
Gardez à l'esprit que si, par exemple, vous utilisez le pilote database
et que vous avez deux domaines partageant la même base de données, vous devez utiliser deux files d'attente distinctes si vous souhaitez gérer les tâches de chaque domaine séparément.
Par exemple, vous pourriez :
QUEUE_DEFAULT=default1
pour site1.com et QUEUE_DEFAULT=default2
pour site2.comqueue.php
en modifiant la file d'attente par défaut en conséquence : 'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => env('QUEUE_DEFAULT','default'),
'retry_after' => 90,
],
php artisan queue:work --domain=site1.com --queue=default1
et
php artisan queue:work --domain=site1.com --queue=default2
Évidemment, la même chose peut être faite pour chaque autre pilote de file d'attente, à l'exception du pilote sync
.
storage:link
Si vous utilisez la commande storage:link
et que vous souhaitez un lien symbolique distinct pour chaque domaine, vous devez les créer manuellement car à ce jour, une telle commande crée toujours un lien nommé storage
et ce nom est codé en dur dans la commande. L'extension de la storage:link
permettant de choisir le nom sort du cadre de ce package (et j'espère que cela se fera directement dans les futures versions de Laravel).
Un moyen d’obtenir plusieurs liens de stockage pourrait être le suivant. Supposons qu'il y ait deux domaines, à savoir site1.com
et site2.com
avec les dossiers de stockage associés storage/site1_com
et storage/site2_com
.
ln -s storage/site1_com/app/public public/storage-site1_com
ln -s storage/site2_com/app/public public/storage-site2_com
.env.site1.com
et .env.site2.com
nous ajoutons une entrée, par exemple pour le premier domaine : APP_PUBLIC_STORAGE=-site1_com
filesystems.php
, nous modifions comme suit : 'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage'.env('APP_PUBLIC_STORAGE'),
'visibility' => 'public',
],
De plus, si vous utilisez le package dans un paramètre d'application à page unique (SPA), vous pourriez mieux gérer des ressources publiques distinctes pour chaque domaine via .htaccess ou des solutions similaires, comme l'a souligné Scaenicus dans sa solution .htaccess.
A partir de la version 1.1.11 un deuxième argument a été ajouté au constructeur Application afin de choisir le dossier où placer les fichiers d'environnement : si vous avez des dizaines de domaines, ce n'est pas très agréable d'avoir des fichiers d'environnement à la racine de l'application de Laravel dossier.
Donc, si vous souhaitez utiliser un dossier différent, ajoutez-le simplement tout en haut du fichier bootstrap/app.php
. par exemple, si vous souhaitez ajouter des fichiers d'environnement au sous-dossier envs
, faites simplement :
//use Illuminate F oundation A pplication ;
use Gecche Multidomain Foundation Application ;
use Illuminate Foundation Configuration Exceptions ;
use Illuminate Foundation Configuration Middleware ;
$ environmentPath = dirname ( __DIR__ ) . DIRECTORY_SEPARATOR . ' envs ' ;
$ domainParams = [];
return Application:: configure (basePath: dirname ( __DIR__ ),
environmentPath: $ environmentPath ,
domainParams: $ domainParams )
-> withRouting (
web: __DIR__ . ' /../routes/web.php ' ,
commands: __DIR__ . ' /../routes/console.php ' ,
health: ' /up ' ,
)
-> withMiddleware ( function ( Middleware $ middleware ) {
//
})
-> withExceptions ( function ( Exceptions $ exceptions ) {
//
})-> create ();
Si vous ne spécifiez pas le deuxième argument, le dossier standard est utilisé. Veuillez noter que si vous spécifiez un dossier, le fichier standard .env
doit également y être placé.
Si vous essayez d'exécuter une page Web ou une commande shell sous un certain domaine, par exemple sub1.site1.com
et qu'il n'existe aucun fichier d'environnement spécifique pour ce domaine, c'est-à-dire que le fichier .env.sub1.site1.com
n'existe pas, le Le package utilisera le premier fichier d’environnement disponible en divisant le nom de domaine par des points. Dans cet exemple, le package recherche le premier fichier d'environnement parmi les suivants :
.env.site1.com
.env.com
.env
La même logique s'applique également au dossier de stockage.
Si dans votre configuration vous utilisez le planificateur de Laravel, n'oubliez pas que la commande schedule:run
doit également être lancée avec l'option domain. Par conséquent, vous devez lancer un planificateur pour chaque domaine. Au début, on pourrait penser qu'une instance du planificateur devrait gérer les commandes lancées pour n'importe quel domaine, mais le planificateur lui-même est exécuté dans une application Laravel, donc "env" sous lequel il est exécuté s'applique automatiquement à chaque commande planifiée et --domain
l'option --domain
n'a aucun effet.
La même chose s'applique aux outils externes comme Supervisor : si vous utilisez Supervisor pour des commandes artisanales, par exemple la commande queue:work
, assurez-vous de préparer une commande pour chaque domaine que vous souhaitez gérer.
En raison de ce qui précède, il existe certains cas dans lesquels le package ne peut pas fonctionner : dans les paramètres où vous n'avez pas la possibilité de modifier par exemple la configuration du superviseur plutôt que les entrées crontab
du planificateur. Un tel exemple a été signalé ici dans lequel une instance Docker a été utilisée.
Enfin, sachez que certaines commandes Laravel appellent d'autres commandes Artisan de l'intérieur, évidemment sans l'option --domain
. La situation ci-dessus ne fonctionne pas correctement car la sous-commande fonctionnera avec le fichier d'environnement standard. Un exemple est la commande migrate
lors de l'utilisation de l'option --seed
.