lisandrop05/laravel-multidomain

基于子域的多租户设置下的 Laravel 应用(这是 'gecche/laravel-multidomain' 的分支,支持 Laravel 10)

v6.0 2023-02-16 13:51 UTC

This package is auto-updated.

Last update: 2024-09-16 17:06:33 UTC


README

Laravel Laravel Laravel Laravel Laravel Laravel License

Laravel Multi Domain

用于在多域名环境下使用 Laravel 的扩展

Laravel Multi Domain

描述

此包允许单个 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 包更多的配置步骤。

安装步骤

  1. 通过修改 bootstrap/app.php 文件顶部的以下行,将整个 Laravel 容器替换。
//$app = new Illuminate\Foundation\Application(
$app = new Lisandrop05\Multidomain\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
  1. 更新两个应用程序内核(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;
  1. config/app.php 文件中的 $providers 数组中用扩展的 QueueServiceProvider 覆盖 QueueServiceProvider
        //Illuminate\Queue\QueueServiceProvider::class,
        Lisandrop05\Multidomain\Queue\QueueServiceProvider::class,
  1. 发布配置文件。
php artisan vendor:publish 

(此包使用发现功能。)

按照上述步骤,您的应用程序将知道其运行的 HTTP 域名,包括 HTTP 和 CLI 请求,以及队列支持。

使用方法

此包添加了三个命令来管理您的应用程序 HTTP 域名

domain.add artisan 命令

主命令是 domain:add 命令,它接受要添加到应用程序的 HTTP 域名的名称作为参数。假设我们有两个域名,site1.comsite2.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:adddomain: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:workqueue: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.comsite2.com,以及相关的存储文件夹storage/site1_comstorage/site2_com

  1. 我们为每个域名手动创建链接
ln -s storage/site1_com/app/public public/storage-site1_com 
ln -s storage/site2_com/app/public public/storage-site2_com 
  1. .env.site1.com.env.site2.com中添加条目,例如,对于第一个域名
APP_PUBLIC_STORAGE=-site1_com
  1. 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实例。