funkymed / tenant-aware-bundle
适用于多租户应用的 Symfony 扩展包
v0.1
2024-06-03 19:32 UTC
Requires
- php: ^8.0
- doctrine/orm: ^3.2
- symfony/console: ^6.0
- symfony/framework-bundle: ^6.0
This package is not auto-updated.
Last update: 2024-09-22 15:54:24 UTC
README
Tenant Aware Bundle 帮助您管理应用程序的多个配置。
配置来自数据库。
安装
composer require funkymed/tenant-aware-bundle
创建配置文件 config/packages/tenant_aware.yaml
tenant_aware: processors: - Funkymed\TenantAwareBundle\DependencyInjection\Compiler\Processor\DummyProcessor - Funkymed\TenantAwareBundle\DependencyInjection\Compiler\Processor\DatabaseProcessor
修改 Kernel.php
以使用按租户缓存的配置
<?php // src/Kernel.php namespace App; use Funkymed\TenantAwareBundle\TenantAwareKernel; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\HttpKernel\Kernel as BaseKernel; class Kernel extends BaseKernel { use MicroKernelTrait; private ?string $hostname; public function __construct( string $environment, bool $debug, string $hostname ) { parent::__construct($environment, $debug); $this->hostname = $hostname; } public function getCacheDir(): string { if ($this->getHostname()) { return $this->getProjectDir().'/var/cache/'.$this->environment.'/'.$this->getHostname(); } return $this->getProjectDir().'/var/cache/'.$this->environment; } public function getLogDir(): string { if ($this->getHostname()) { return $this->getProjectDir().'/var/log/'.$this->getHostname(); } return $this->getProjectDir().'/var/log'; } public function getName() { return str_replace('-', '_', $this->getHostname()); } public function getKernelParameters(): array { $parameters = parent::getKernelParameters(); $parameters['kernel.hostname'] = $this->getHostname(); return $parameters; } public function getHostname() { $hostname = $this->getHost(); return $hostname ? $hostname : $this->hostname; } public function getHost() { $possibleHostSources = array('HTTP_X_FORWARDED_HOST', 'HTTP_HOST', 'SERVER_NAME', 'SERVER_ADDR'); $sourceTransformations = array( "HTTP_X_FORWARDED_HOST" => function ($value) { $elements = explode(',', $value); return trim(end($elements)); } ); $host = ''; foreach ($possibleHostSources as $source) { if (!empty($host)) { break; } if (empty($_SERVER[$source])) { continue; } $host = $_SERVER[$source]; if (array_key_exists($source, $sourceTransformations)) { $host = $sourceTransformations[$source]($host); } } // Remove port number from host $host = preg_replace('/:\d+$/', '', $host); return trim($host); } }
然后将 bin/console
替换为以下代码以实现兼容性
#!/usr/bin/env php <?php // bin/console use App\Kernel; use Funkymed\TenantAwareBundle\Command\TenantAwareApplication; use Symfony\Component\Console\Input\ArgvInput; if (!is_dir(dirname(__DIR__).'/vendor')) { throw new LogicException('Dependencies are missing. Try running "composer install".'); } if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) { throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".'); } require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; return function (array $context) { $input = new ArgvInput(); $env = $input->getParameterOption(['--env', '-e'], getenv('APP_ENV') ?: 'dev'); $debug = getenv('APP_DEBUG') !== '0' && $env !== 'prod'; // Added support for tenant $hostname = $input->getParameterOption('--tenant'); $kernel = new Kernel($env, $debug, $hostname); $kernel->boot(); return new TenantAwareApplication($kernel); };
现在您可以使用 symfony 的默认命令,但带有租户配置
bin/console d:d:c --tenant=localhost
租户参数是您要获取配置的主机名
配置
在 .env
和 config/packages/doctrine.yaml
中添加您的数据库配置
# .env DATABASE_HOST="localhost" DATABASE_USER="root" DATABASE_PASSWORD="" DATABASE_NAME="tenant"
doctrine: dbal: driver: 'pdo_mysql' server_version: '8' use_savepoints: true host: '%env(resolve:DATABASE_HOST)%' port: 3306 user: '%env(resolve:DATABASE_USER)%' password: '%env(resolve:DATABASE_URL)%' dbname: '%env(resolve:DATABASE_PASSWORD)%'
创建租户数据库
bin/console d:d:c --if-not-exist bin/console d:s:u -f
向您的数据库添加内容以管理不同的主机名(参见租户实体)
添加您的处理器
添加更多服务
您还可以处理数据库以外的其他服务。您可能希望根据主机名更改 AWS S3、Redis 或 RabbitMQ。
只需复制 TenantAwareBundle/DependencyInjection/Compiler/Processor/DummyProcessor.php
并将其放入您的 DependencyInjection/Compiler/Processor
命名空间
在处理器中添加您想要替换的内容
<?php // src/DependencyInjection/DependencyInjection/Compiler/Processor/DummyProcessor.php namespace App\DependencyInjection\Compiler\Processor; // use this as an exemple to create your own replacement configuration class MyProcessor extends ProcessorAbstract { public function process() { // get current definition $definition = $this->container->getDefinition('doctrine.dbal.default_connection'); $configuration = $definition->getArguments(); // update it from the tenant information $configuration[0]["host"] = $this->tenant->getDatabaseHost(); $configuration[0]["dbname"] = $this->tenant->getDatabaseName(); $configuration[0]["user"] = $this->tenant->getDatabaseUser(); $configuration[0]["password"] = $this->tenant->getDatabasePassword(); // replace the current configuration everything is in the cache now $definition->replaceArgument(0, $configuration[0]); } }
更新配置
tenant_aware: processors: - App\DependencyInjection\Compiler\Processor\MyProcessor
您可以添加您想要的任何处理器。
您还可以替换实体租户以添加您需要管理租户的字段。