lisandrop05 / laravel-multidomain
基于子域的多租户设置下的 Laravel 应用(这是 'gecche/laravel-multidomain' 的分支,支持 Laravel 10)
Requires
- laravel/framework: ^10.0
Requires (Dev)
- limedeck/phpunit-detailed-printer: ^6.0
- mockery/mockery: ^1.4.4
- orchestra/testbench: 8.x-dev
- orchestra/testbench-browser-kit: ^8.0
- phpunit/phpunit: ^9.5.8
This package is auto-updated.
Last update: 2024-09-16 17:06:33 UTC
README
Laravel Multi Domain
用于在多域名环境下使用 Laravel 的扩展
描述
此包允许单个 Laravel 安装与多个 HTTP 域名一起工作。
有许多情况,不同客户在代码方面使用相同的应用程序,但在数据库、存储和配置方面并不相同。
此包提供了一个非常简单的方法,为每个这样的客户提供特定的环境文件、特定的存储路径和特定的数据库。
文档
版本兼容性
关于兼容性的进一步说明
版本 v1.1.x
- 从 v1.1.0 到 v1.1.5,版本与 Laravel 5.5、5.6、5.7、5.8 或 6.0 完全兼容。
- 从 v1.1.6+ 开始,v1.1.x 版本的发布仅与 Laravel 5.5 兼容,以便正确运行测试。
截至目前,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 相同)
安装
将 gecche/laravel-multidomain 添加到 composer.json 的依赖项中
{ "require": { "gecche/laravel-multidomain": "5.*" } }
使用 composer update 更新您的包,或使用 composer install 安装。
您还可以使用 composer require gecche/laravel-multidomain
添加包,稍后指定您想要的版本(目前,dev-v1.1.* 是最佳选择)。
此包需要在引导过程的非常开始处覆盖 Laravel 核心函数中 HTTP 域名的检测的最小集合,以获取特定的环境文件。因此,此包需要比大多数 Laravel 包更多的配置步骤。
安装步骤
- 通过修改
bootstrap/app.php
文件顶部的以下行,将整个 Laravel 容器替换。
//$app = new Illuminate\Foundation\Application( $app = new Lisandrop05\Multidomain\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__) );
- 更新两个应用程序内核(HTTP 和 CLI)。
在 app/Http/Kernel.php
文件顶部执行以下更改
//use Illuminate\Foundation\Http\Kernel as HttpKernel; use Lisandrop05\Multidomain\Foundation\Http\Kernel as HttpKernel;
在 app/Console/Kernel.php
文件中也类似地执行
//use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use Lisandrop05\Multidomain\Foundation\Console\Kernel as ConsoleKernel;
- 在
config/app.php
文件中的 $providers 数组中用扩展的QueueServiceProvider
覆盖QueueServiceProvider
//Illuminate\Queue\QueueServiceProvider::class, Lisandrop05\Multidomain\Queue\QueueServiceProvider::class,
- 发布配置文件。
php artisan vendor:publish
(此包使用发现功能。)
按照上述步骤,您的应用程序将知道其运行的 HTTP 域名,包括 HTTP 和 CLI 请求,以及队列支持。
使用方法
此包添加了三个命令来管理您的应用程序 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文件和存储路径目录。
该列表保存在config/domain.php
配置文件的domains
键中。
每次运行domain:add
和domain:remove
命令时,此列表都会自动更新。
config:cache
artisan命令
可以像使用任何其他artisan命令一样使用此包的config:cache 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请求,都会加载特定的环境文件并使用特定的存储文件夹。
如果未找到特定的环境文件和/或存储文件夹,则使用标准文件。
通过使用PHP变量$_SERVER['SERVER_NAME']
来检测正确的HTTP域名。
自定义HTTP域名的检测
从版本1.1.15开始,可以通过将一个Closure
作为Application
构造函数的新domainParams
参数的domain_detection_function_web
条目传递来自定义HTTP域名的检测。在以下示例中,HTTP域名的检测依赖于$_SERVER['HTTP_HOST']
而不是$_SERVER['SERVER_NAME']
。
$domainParams = [ 'domain_detection_function_web' => function() { return \Illuminate\Support\Arr::get($_SERVER,'HTTP_HOST'); } ]; //$app = new Illuminate\Foundation\Application( $app = new Lisandrop05\Multidomain\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__), null, $domainParams );
在artisan命令中使用多域名
为了区分域名,每个artisan命令都接受一个新选项:domain
。例如:
php artisan list --domain=site1.com
该命令将使用相应的域名设置。
关于队列
已更新artisan命令queue:work
和queue:listen
以接受一个新选项:domain
。
php artisan queue:work --domain=site1.com
如往常一样,上述命令将使用相应的域名设置。
请注意,如果您使用的是database
驱动程序并且有两个共享相同数据库的域名,那么如果您想分别管理每个域的工作,则应该使用两个不同的队列。
例如,您可以
- 在您的.env文件中为每个域名设置一个默认队列,例如为site1.com设置
QUEUE_DEFAULT=default1
,为site2.com设置QUEUE_DEFAULT=default2
- 通过相应地更改默认队列来更新
queue.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)设置中使用此包,您可以通过类似Scaenicus在.htaccess解决方案中指出的方式通过 .htaccess 或类似解决方案更好地处理每个域的独立公共资源。
将环境文件存储在自定义文件夹中
从版本1.1.11开始,Application构造函数中添加了一个第二个参数,以选择放置环境文件的文件夹:如果您有数十个域名,将环境文件放在Laravel应用程序的根目录中并不是一件令人愉快的事情。
因此,如果您想使用不同的文件夹,只需将其添加到bootstrap/app.php
文件的顶部即可。例如,如果您想将环境文件添加到envs
子文件夹中,只需这样做
//$app = new Illuminate\Foundation\Application( $app = new Lisandrop05\Multidomain\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__), dirname(__DIR__) . DIRECTORY_SEPARATOR . 'envs' );
如果您没有指定第二个参数,则假定标准文件夹。请注意,如果指定了文件夹,也必须在该文件夹中放置标准的.env
文件
默认环境文件和存储文件夹
如果您尝试在某个域名下运行网页或shell命令,例如sub1.site1.com
,并且没有为该域名特定的环境文件,即文件.env.sub1.site1.com
不存在,则该包将使用第一个可用的环境文件,通过点分割域名。在这个例子中,该包在以下文件中搜索第一个环境文件
.env.site1.com
.env.com
.env
相同的逻辑也适用于存储文件夹。
关于Laravel的调度器、监督器和一些限制
如果您在设置中使用了Laravel的调度器,请记住,命令schedule:run
也必须带有域名选项启动。因此,您必须为每个域名启动一个调度器。起初,人们可能会认为一个调度器实例应该处理为任何域名启动的命令,但是调度器本身是在Laravel应用程序中运行的,所以它运行的“环境”自动应用于每个计划的任务,并且--domain
选项没有任何效果。
这同样适用于外部工具,如Supervisor:如果您使用Supervisor用于artisan命令,例如queue:work
命令,请确保为要处理的每个域名准备一个命令。
由于上述原因,有些情况下该包无法工作:在这些设置中,您没有更改例如调度器的crontab
条目而不是supervisor配置的可能性。这种情况已在此处指出,其中一个使用了Docker实例。