在多域设置中使用 Laravel 的扩展
该包允许单个 Laravel 安装使用多个 HTTP 域。
在很多情况下,不同的客户在代码方面使用相同的应用程序,但在数据库、存储和配置方面却不同。
这个包提供了一种非常简单的方法来获取每个此类客户的特定环境文件、特定存储路径和特定数据库。
拉维尔 | 多域 |
---|---|
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 |
发布 v1.1.x:
迄今为止,版本 v1.1.6+、v1.2.x、v1.3.x、v1.4.x、v2.x 和 v3.x 在功能上是等效的。版本已分开,以便与相应版本的 Laravel 框架运行集成测试。
然而,随着 Laravel 8 的发布,版本 v1.1.14、v1.2.8、v1.3.8 和 v1.4.8 是最新版本,包括相应 Laravel 5.x 版本的新功能(该版本的错误修复支持仍然有效) 。 2021-02-13 更新:v1.1+ 版本的一些最新功能仍在进行中:)
v1.0 需要 Laravel 5.1、5.2、5.3 和 5.4(与 Laravel 5.4 相比,不再维护和测试,但包的用法与 1.1 相同)
2023-02-20 更新:从 Laravel 10.x 开始,包版本遵循相同的编号。
添加 gecche/laravel-multidomain 作为 Composer.json 的要求:
{
"require" : {
"gecche/laravel-multidomain" : "11.*"
}
}
使用composer update 更新您的软件包或使用composer install 进行安装。
您还可以使用composer require gecche/laravel-multidomain
添加包,然后指定您想要的版本。
该包需要在引导过程一开始就覆盖 Laravel 核心函数的最小集合中对 HTTP 域的检测,以便获取特定的环境文件。所以这个包比大多数 Laravel 包需要更多的配置步骤。
安装步骤:
bootstrap/app.php
文件最顶部的以下行来替换整个 Laravel 容器。 //use Illuminate F oundation A pplication
use Gecche Multidomain Foundation Application
config/app.php
文件中的扩展版本覆盖QueueServiceProvider
,如下所示: ' 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 (),
请注意,如果您由于其他原因更改了config/app.php
文件,则该文件中可能已经存在上述providers
条目,唯一重要的行是替换QueueServiceProvider
的行。
php artisan vendor:publish
(这个包利用了发现功能。)
按照上述步骤,您的应用程序将了解正在运行的 HTTP 域,包括 HTTP 和 CLI 请求,包括队列支持。
注意:在 Laravel 11 中,安装比以前更简单:如果您使用以前版本的 Laravel,请查看文档中的安装步骤。
该软件包与 Horizon 兼容,这得益于社区的贡献。如果您需要将此软件包与 Horizon 一起使用,则必须遵循其他两个安装步骤:
像往常一样安装 Laravel Horizon
替换 app/Providers/HorizonServiceProvider.php 文件最顶部的 Laravel Horizon 导入。
//use Laravel H orizon H orizonApplicationServiceProvider ;
use Gecche Multidomain Horizon HorizonApplicationServiceProvider ;
该软件包添加了三个命令来管理您的应用程序 HTTP 域:
domain.add
artisan 命令主要命令是domain:add
命令,它将要添加到应用程序的HTTP 域的名称作为参数。假设我们有两个域site1.com
和site2.com
,共享相同的代码。
我们简单地做:
php artisan domain:add site1.com
和
php artisan domain:add site2.com
这些命令创建两个新的环境文件.env.site1.com
和.env.site2.com
,您可以在其中放置每个站点的特定配置(例如数据库配置、缓存配置和其他配置,通常在环境中找到)文件)。
该命令还在config/domains.php
文件的domains
键中添加一个条目。
此外,还会创建两个新文件夹: storage/site1_com/
和storage/site2_com/
。它们具有与主存储相同的文件夹结构。
对此storage
结构的自定义必须与config/domain.php
文件中的值匹配。
domain.remove
artisan 命令domain:remove
命令通过删除应用程序的环境文件来删除指定的 HTTP 域。例如:
php artisan domain:remove site2.com
添加force
选项将删除域存储文件夹。
该命令还会从config/domains.php
文件中的domains
键中删除相应的条目。
domain.update_env
artisan 命令domain:update_env
命令传递一个 json 编码的数据数组来更新一个或所有环境文件。这些值将添加到相应 .env 的末尾。
通过添加domain
参数来更新单个域环境文件。
当domain
参数不存在时,该命令将更新所有环境文件,包括标准.env
文件。
要更新的域列表保存在domain.php
配置文件中。
例如:
php artisan domain:update_env --domain_values='{"TOM_DRIVER":"TOMMY"}'
会将TOM_DRIVER=TOMMY
行添加到所有域环境文件中。
domain.list
artisan 命令domain:list
命令列出当前安装的域及其 .env 文件和存储路径 dir。
该列表保存在config/domain.php
配置文件的domains
键中。
此列表会在每次运行domain:add
和domain:remove
命令时自动更新。
config:cache
artisan 命令config:cache artisan 命令可以与此包一起使用,就像任何其他 artisan 命令一样。
请注意,此命令将为执行该命令的每个域生成一个 config.php 文件。即命令
php artisan config:cache --domain=site2.com
将生成文件
config-site2_com.php
在运行时,当前的 HTTP 域被维护在 laravel 容器中,并且可以通过该包添加的domain()
方法来访问。
可以使用domainList()
方法。它返回一个包含已安装域信息的关联数组,类似于上面的domain.list
命令。
例如
[
site1.com => [
'storage_path' => <LARAVEL-STORAGE-PATH>/site1_com,
'env' => '.env.site1.com'
]
]
对于应用程序收到的每个 HTTP 请求,都会加载特定的环境文件并使用特定的存储文件夹。
如果未找到特定环境文件和/或存储文件夹,则使用标准环境文件和/或存储文件夹。
正确 HTTP 域的检测是通过使用$_SERVER['SERVER_NAME']
PHP 变量来完成的。
重要提示:在某些执行环境中 $_SERVER['SERVER_NAME'] 未实例化,因此在您按如下所述自定义 HTTP 域的检测之前,此包无法正常工作。
从版本 1.1.15 开始,可以自定义 HTTP 域的检测,将Closure
传递为Application
构造函数的新domainParams
参数的domain_detection_function_web
条目。在以下示例中,HTTP 域检测依赖于$_SERVER['HTTP_HOST']
而不是$_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 ();
为了区分域,每个 artisan 命令都接受一个新选项: domain
。例如:
php artisan list --domain=site1.com
该命令将使用相应的域设置。
artisan 命令queue:work
和queue:listen
命令已更新以接受新的domain
选项。
php artisan queue:work --domain=site1.com
与往常一样,上述命令将使用相应的域设置。
请记住,例如,如果您正在使用database
驱动程序,并且有两个域共享同一个数据库,那么如果您想单独管理每个域的作业,则应该使用两个不同的队列。
例如,您可以:
QUEUE_DEFAULT=default1
for site1.com 和QUEUE_DEFAULT=default2
for site2.comqueue.php
配置文件: 'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => env('QUEUE_DEFAULT','default'),
'retry_after' => 90,
],
php artisan queue:work --domain=site1.com --queue=default1
和
php artisan queue:work --domain=site1.com --queue=default2
显然,除了sync
驱动程序之外,还可以对每个其他队列驱动程序执行相同的操作。
storage:link
命令如果您使用storage:link
命令并且希望为每个域创建一个不同的符号链接,则必须手动创建它们,因为到目前为止,此类命令总是创建一个名为storage
链接,并且该名称在命令中硬编码。扩展storage:link
命令允许选择名称超出了这个包的范围(我希望它能在 Laravel 的未来版本中直接完成)。
获取多个存储链接的方法可能如下。让我们假设有两个域,即site1.com
和site2.com
以及关联的存储文件夹storage/site1_com
和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
和.env.site2.com
中,我们添加一个条目,例如第一个域: APP_PUBLIC_STORAGE=-site1_com
filesystems.php
配置文件中,我们更改如下: 'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage'.env('APP_PUBLIC_STORAGE'),
'visibility' => 'public',
],
此外,如果您在单页应用程序 (SPA) 设置中使用该包,您可以通过 .htaccess 或 Scaenicus 在其 .htaccess 解决方案中指出的类似解决方案更好地处理每个域的不同公共资源。
从版本 1.1.11 开始,第二个参数已添加到 Application 构造函数中,以便选择放置环境文件的文件夹:如果您有数十个域,则将环境文件放在 Laravel 应用程序的根目录中并不是很愉快文件夹。
因此,如果您想使用不同的文件夹,只需将其添加到bootstrap/app.php
文件的最顶部即可。例如,如果要将环境文件添加到envs
子文件夹中,只需执行以下操作:
//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 ();
如果不指定第二个参数,则假定为标准文件夹。请注意,如果您指定文件夹,则标准.env
文件也必须放置在其中
如果您尝试在某个域(例如sub1.site1.com
下运行网页或 shell 命令,并且该域没有特定的环境文件,即文件.env.sub1.site1.com
不存在,则软件包将通过用点分割域名来使用第一个可用的环境文件。在此示例中,包在以下文件中搜索第一个环境文件:
.env.site1.com
.env.com
.env
同样的逻辑也适用于存储文件夹。
如果在您的设置中使用 Laravel 的调度程序,请记住命令schedule:run
也必须使用域选项启动。因此,您必须为每个域启动一个调度程序。一开始,人们可能会认为一个 Scheduler 实例应该处理为任何域启动的命令,但 Scheduler 本身是在 Laravel 应用程序中运行的,因此它运行的“env”会自动应用于每个计划的命令,并且--domain
选项根本没有任何作用。
这同样适用于像 Supervisor 这样的外部工具:如果您使用 Supervisor 来执行 artisan 命令,例如queue:work
命令,请务必为您要处理的每个域准备一个命令。
由于上述原因,在某些情况下该包无法工作:在这些设置中,您无法更改例如主管配置而不是调度程序的crontab
条目。这里已经指出了这样一个使用 Docker 实例的示例。
最后,请注意,某些 Laravel 命令从内部调用其他 Artisan 命令,显然没有--domain
选项。上述情况无法正常工作,因为子命令将使用标准环境文件。一个示例是使用--seed
选项时的migrate
命令。