mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-23 16:45:35 +08:00
add environment variables support (#255)
This commit is contained in:
@@ -29,7 +29,8 @@
|
|||||||
"symfony/console": "^6.0",
|
"symfony/console": "^6.0",
|
||||||
"symfony/polyfill-ctype": "^1.19",
|
"symfony/polyfill-ctype": "^1.19",
|
||||||
"symfony/polyfill-mbstring": "^1.19",
|
"symfony/polyfill-mbstring": "^1.19",
|
||||||
"symfony/routing": "~6.0 || ~5.0 || ~4.0"
|
"symfony/routing": "~6.0 || ~5.0 || ~4.0",
|
||||||
|
"vlucas/phpdotenv": "^5.5"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"captainhook/captainhook": "^5.10",
|
"captainhook/captainhook": "^5.10",
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ declare(strict_types=1);
|
|||||||
use OneBot\Driver\Driver;
|
use OneBot\Driver\Driver;
|
||||||
use OneBot\Driver\Process\ProcessManager;
|
use OneBot\Driver\Process\ProcessManager;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use ZM\Config\Environment;
|
||||||
|
use ZM\Config\EnvironmentInterface;
|
||||||
use ZM\Framework;
|
use ZM\Framework;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -24,5 +26,6 @@ return [
|
|||||||
'worker_id' => fn () => ProcessManager::getProcessId(),
|
'worker_id' => fn () => ProcessManager::getProcessId(),
|
||||||
Driver::class => fn () => Framework::getInstance()->getDriver(),
|
Driver::class => fn () => Framework::getInstance()->getDriver(),
|
||||||
LoggerInterface::class => fn () => logger(),
|
LoggerInterface::class => fn () => logger(),
|
||||||
|
EnvironmentInterface::class => Environment::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
/* 启动框架的底层驱动(原生支持 swoole、workerman 两种) */
|
/* 启动框架的底层驱动(原生支持 swoole、workerman 两种) */
|
||||||
$config['driver'] = 'workerman';
|
$config['driver'] = env('DRIVER', 'workerman');
|
||||||
|
|
||||||
/* 要启动的服务器监听端口及协议 */
|
/* 要启动的服务器监听端口及协议 */
|
||||||
$config['servers'] = [
|
$config['servers'] = [
|
||||||
@@ -22,14 +22,14 @@ $config['servers'] = [
|
|||||||
|
|
||||||
/* Workerman 驱动相关配置 */
|
/* Workerman 驱动相关配置 */
|
||||||
$config['workerman_options'] = [
|
$config['workerman_options'] = [
|
||||||
'worker_num' => 1, // 如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算,则可把这里改为1使用全局变量
|
'worker_num' => env('WORKER_NUM', 1), // 如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算,则可把这里改为1使用全局变量
|
||||||
];
|
];
|
||||||
|
|
||||||
/* Swoole 驱动相关配置 */
|
/* Swoole 驱动相关配置 */
|
||||||
$config['swoole_options'] = [
|
$config['swoole_options'] = [
|
||||||
'coroutine_hook_flags' => SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL), // 协程 Hook 内容
|
'coroutine_hook_flags' => SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL), // 协程 Hook 内容
|
||||||
'swoole_set' => [
|
'swoole_set' => [
|
||||||
'worker_num' => 1, // 如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算,则可把这里改为1使用全局变量
|
'worker_num' => env('WORKER_NUM', 1), // 如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算,则可把这里改为1使用全局变量
|
||||||
'dispatch_mode' => 2, // 包分配原则,见 https://wiki.swoole.com/#/server/setting?id=dispatch_mode
|
'dispatch_mode' => 2, // 包分配原则,见 https://wiki.swoole.com/#/server/setting?id=dispatch_mode
|
||||||
'max_coroutine' => 300000, // 允许最大的协程数
|
'max_coroutine' => 300000, // 允许最大的协程数
|
||||||
'max_wait_time' => 5, // 安全退出模式下允许等待 Worker 的最长秒数
|
'max_wait_time' => 5, // 安全退出模式下允许等待 Worker 的最长秒数
|
||||||
@@ -51,7 +51,7 @@ $config['runtime'] = [
|
|||||||
],
|
],
|
||||||
'namespace' => [],
|
'namespace' => [],
|
||||||
],
|
],
|
||||||
'timezone' => 'Asia/Shanghai',
|
'timezone' => env('TIMEZONE', 'Asia/Shanghai'),
|
||||||
];
|
];
|
||||||
|
|
||||||
/* 允许加载插件形式 */
|
/* 允许加载插件形式 */
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use OneBot\Driver\Coroutine\CoroutineInterface;
|
|||||||
use OneBot\Driver\Process\ExecutionResult;
|
use OneBot\Driver\Process\ExecutionResult;
|
||||||
use OneBot\V12\Object\MessageSegment;
|
use OneBot\V12\Object\MessageSegment;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use ZM\Config\Environment;
|
||||||
use ZM\Config\ZMConfig;
|
use ZM\Config\ZMConfig;
|
||||||
use ZM\Container\ContainerHolder;
|
use ZM\Container\ContainerHolder;
|
||||||
use ZM\Logger\ConsoleLogger;
|
use ZM\Logger\ConsoleLogger;
|
||||||
@@ -268,3 +269,12 @@ function kv(string $name = ''): Psr\SimpleCache\CacheInterface
|
|||||||
/* @phpstan-ignore-next-line */
|
/* @phpstan-ignore-next-line */
|
||||||
return is_a($kv_class, KVInterface::class, true) ? $kv_class::open($name) : new $kv_class($name);
|
return is_a($kv_class, KVInterface::class, true) ? $kv_class::open($name) : new $kv_class($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取环境变量
|
||||||
|
*/
|
||||||
|
function env(string $key, mixed $default = null): mixed
|
||||||
|
{
|
||||||
|
// TODO: 重新思考容器绑定的加载方式,从而在此处使用 interface
|
||||||
|
return resolve(Environment::class)->get($key, $default);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,13 +4,20 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ZM\Bootstrap;
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
|
use Dotenv\Dotenv;
|
||||||
use OneBot\Driver\Workerman\Worker;
|
use OneBot\Driver\Workerman\Worker;
|
||||||
|
use ZM\Config\Environment;
|
||||||
|
use ZM\Config\EnvironmentInterface;
|
||||||
use ZM\Config\ZMConfig;
|
use ZM\Config\ZMConfig;
|
||||||
|
|
||||||
class LoadConfiguration
|
class LoadConfiguration
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(array $config): void
|
||||||
{
|
{
|
||||||
|
// TODO: 重新思考容器绑定的加载方式,从而在此处使用 interface
|
||||||
|
$env = resolve(Environment::class);
|
||||||
|
$this->loadEnvVariables($env);
|
||||||
|
|
||||||
$config_i = config();
|
$config_i = config();
|
||||||
$config_i->addConfigPath($this->getConfigDir($config));
|
$config_i->addConfigPath($this->getConfigDir($config));
|
||||||
$config_i->setEnvironment($this->getConfigEnvironment($config));
|
$config_i->setEnvironment($this->getConfigEnvironment($config));
|
||||||
@@ -68,4 +75,20 @@ class LoadConfiguration
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function loadEnvVariables(EnvironmentInterface $env): void
|
||||||
|
{
|
||||||
|
$dotenv_path = $env->get('DOTENV_PATH', SOURCE_ROOT_DIR . '/.env');
|
||||||
|
|
||||||
|
if (!file_exists($dotenv_path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = dirname($dotenv_path);
|
||||||
|
$file = basename($dotenv_path);
|
||||||
|
|
||||||
|
foreach (Dotenv::createImmutable($path, $file)->load() as $key => $value) {
|
||||||
|
$env->set($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
82
src/ZM/Config/Environment.php
Normal file
82
src/ZM/Config/Environment.php
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ZM\Config;
|
||||||
|
|
||||||
|
class Environment implements EnvironmentInterface
|
||||||
|
{
|
||||||
|
private const VALUE_MAP = [
|
||||||
|
'true' => true,
|
||||||
|
'(true)' => true,
|
||||||
|
'false' => false,
|
||||||
|
'(false)' => false,
|
||||||
|
'null' => null,
|
||||||
|
'(null)' => null,
|
||||||
|
'empty' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
private array $values;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $values 额外的环境变量,优先级高于系统环境变量
|
||||||
|
* @param bool $overwrite 是否允许后续 set() 覆盖已有的环境变量
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
array $values = [],
|
||||||
|
private bool $overwrite = false
|
||||||
|
) {
|
||||||
|
$this->values = $values + $_ENV + $_SERVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function set(string $name, mixed $value): self
|
||||||
|
{
|
||||||
|
if (array_key_exists($name, $this->values) && !$this->overwrite) {
|
||||||
|
// 如不允许覆盖已有的环境变量,则不做任何操作
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->values[$name] = $_ENV[$name] = $value;
|
||||||
|
putenv("{$name}={$value}");
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function get(string $name, mixed $default = null): mixed
|
||||||
|
{
|
||||||
|
if (isset($this->values[$name])) {
|
||||||
|
return $this->normalize($this->values[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getAll(): array
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach ($this->values as $key => $value) {
|
||||||
|
$result[$key] = $this->normalize($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function normalize(mixed $value): mixed
|
||||||
|
{
|
||||||
|
if (!is_string($value)) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::VALUE_MAP[strtolower($value)] ?? $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/ZM/Config/EnvironmentInterface.php
Normal file
23
src/ZM/Config/EnvironmentInterface.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ZM\Config;
|
||||||
|
|
||||||
|
interface EnvironmentInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 设置环境变量
|
||||||
|
*/
|
||||||
|
public function set(string $name, mixed $value): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取环境变量
|
||||||
|
*/
|
||||||
|
public function get(string $name, mixed $default = null): mixed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有环境变量
|
||||||
|
*/
|
||||||
|
public function getAll(): array;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user