mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-21 15:45:36 +08:00
refactor framework kernel
This commit is contained in:
12
src/ZM/Bootstrap/Bootstrapper.php
Normal file
12
src/ZM/Bootstrap/Bootstrapper.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
|
use ZM\Kernel;
|
||||||
|
|
||||||
|
interface Bootstrapper
|
||||||
|
{
|
||||||
|
public function bootstrap(Kernel $kernel): void;
|
||||||
|
}
|
||||||
@@ -6,10 +6,11 @@ namespace ZM\Bootstrap;
|
|||||||
|
|
||||||
use OneBot\Exception\ExceptionHandler;
|
use OneBot\Exception\ExceptionHandler;
|
||||||
use ZM\Exception\Handler;
|
use ZM\Exception\Handler;
|
||||||
|
use ZM\Kernel;
|
||||||
|
|
||||||
class HandleExceptions
|
class HandleExceptions implements Bootstrapper
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(Kernel $kernel): void
|
||||||
{
|
{
|
||||||
// 注册全局错误处理器
|
// 注册全局错误处理器
|
||||||
set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) {
|
set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) {
|
||||||
|
|||||||
@@ -5,75 +5,24 @@ declare(strict_types=1);
|
|||||||
namespace ZM\Bootstrap;
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
use Dotenv\Dotenv;
|
use Dotenv\Dotenv;
|
||||||
use OneBot\Driver\Workerman\Worker;
|
|
||||||
use ZM\Config\Environment;
|
use ZM\Config\Environment;
|
||||||
use ZM\Config\EnvironmentInterface;
|
use ZM\Config\EnvironmentInterface;
|
||||||
use ZM\Config\ZMConfig;
|
use ZM\Config\ZMConfig;
|
||||||
|
use ZM\Kernel;
|
||||||
|
|
||||||
class LoadConfiguration
|
class LoadConfiguration implements Bootstrapper
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(Kernel $kernel): void
|
||||||
{
|
{
|
||||||
// TODO: 重新思考容器绑定的加载方式,从而在此处使用 interface
|
// TODO: 重新思考容器绑定的加载方式,从而在此处使用 interface
|
||||||
$env = resolve(Environment::class);
|
$env = resolve(Environment::class);
|
||||||
$this->loadEnvVariables($env);
|
$this->loadEnvVariables($env);
|
||||||
|
|
||||||
$config_i = config();
|
new ZMConfig([
|
||||||
$config_i->addConfigPath($this->getConfigDir($config));
|
'source' => [
|
||||||
$config_i->setEnvironment($this->getConfigEnvironment($config));
|
'paths' => [$kernel->getConfigDir()],
|
||||||
$this->parseArgvToConfig($config, $config_i);
|
],
|
||||||
}
|
]);
|
||||||
|
|
||||||
private function getConfigDir(array $config): string
|
|
||||||
{
|
|
||||||
$config_dir = $config['config-dir'] ?? null;
|
|
||||||
// 默认配置文件目录
|
|
||||||
$find_dir = [
|
|
||||||
WORKING_DIR . '/config',
|
|
||||||
SOURCE_ROOT_DIR . '/config',
|
|
||||||
];
|
|
||||||
// 如果启动参数指定了配置文件目录,则优先使用
|
|
||||||
if ($config_dir !== null) {
|
|
||||||
array_unshift($find_dir, $config_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历目录,找到第一个存在的目录
|
|
||||||
foreach ($find_dir as $dir) {
|
|
||||||
if (is_dir($dir)) {
|
|
||||||
return $dir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有找到目录,则抛出异常
|
|
||||||
throw new \RuntimeException('No config directory found');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getConfigEnvironment(array $config): string
|
|
||||||
{
|
|
||||||
return $config['env'] ?? 'development';
|
|
||||||
}
|
|
||||||
|
|
||||||
private function parseArgvToConfig(array $argv, ZMConfig $config): void
|
|
||||||
{
|
|
||||||
foreach ($argv as $x => $y) {
|
|
||||||
// 当值为 true/false 时,表示该参数为可选参数。当值为 null 时,表示该参数必定会有一个值,如果是 null,说明没指定
|
|
||||||
if ($y === false || is_null($y)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch ($x) {
|
|
||||||
case 'driver': // 动态设置驱动类型
|
|
||||||
$config->set('global.driver', $y);
|
|
||||||
break;
|
|
||||||
case 'worker-num': // 动态设置 Worker 数量
|
|
||||||
$config->set('global.swoole_options.swoole_set.worker_num', (int) $y);
|
|
||||||
$config->set('global.workerman_options.workerman_worker_num', (int) $y);
|
|
||||||
break;
|
|
||||||
case 'daemon': // 启动为守护进程
|
|
||||||
$config->set('global.swoole_options.swoole_set.daemonize', 1);
|
|
||||||
Worker::$daemonize = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadEnvVariables(EnvironmentInterface $env): void
|
private function loadEnvVariables(EnvironmentInterface $env): void
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ZM\Bootstrap;
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
class LoadGlobalDefines
|
use ZM\Kernel;
|
||||||
|
|
||||||
|
class LoadGlobalDefines implements Bootstrapper
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(Kernel $kernel): void
|
||||||
{
|
{
|
||||||
require FRAMEWORK_ROOT_DIR . '/src/Globals/global_defines_framework.php';
|
require FRAMEWORK_ROOT_DIR . '/src/Globals/global_defines_framework.php';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ZM\Bootstrap;
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
|
use ZM\Kernel;
|
||||||
use ZM\Plugin\PluginManager;
|
use ZM\Plugin\PluginManager;
|
||||||
|
|
||||||
class LoadPlugins
|
class LoadPlugins implements Bootstrapper
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(Kernel $kernel): void
|
||||||
{
|
{
|
||||||
// 先遍历下插件目录下是否有这个插件,没有这个插件则不能打包
|
// 先遍历下插件目录下是否有这个插件,没有这个插件则不能打包
|
||||||
$plugin_dir = config('global.plugin.load_dir', SOURCE_ROOT_DIR . '/plugins');
|
$plugin_dir = config('global.plugin.load_dir', SOURCE_ROOT_DIR . '/plugins');
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace ZM\Bootstrap;
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
use ZM\Event\EventProvider;
|
use ZM\Event\EventProvider;
|
||||||
|
use ZM\Kernel;
|
||||||
|
|
||||||
class RegisterEventProvider
|
class RegisterEventProvider implements Bootstrapper
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(Kernel $kernel): void
|
||||||
{
|
{
|
||||||
global $ob_event_provider;
|
global $ob_event_provider;
|
||||||
$ob_event_provider = EventProvider::getInstance();
|
$ob_event_provider = EventProvider::getInstance();
|
||||||
|
|||||||
@@ -4,18 +4,17 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ZM\Bootstrap;
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
|
use ZM\Kernel;
|
||||||
use ZM\Logger\ConsoleLogger;
|
use ZM\Logger\ConsoleLogger;
|
||||||
|
|
||||||
class RegisterLogger
|
class RegisterLogger implements Bootstrapper
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(Kernel $kernel): void
|
||||||
{
|
{
|
||||||
// 初始化 Logger
|
// 初始化 Logger
|
||||||
if (!ob_logger_registered()) {
|
if (!ob_logger_registered()) {
|
||||||
$debug = $config['verbose'] ?? false;
|
|
||||||
$debug = $debug ? 'debug' : null;
|
|
||||||
// 如果没有注册过 Logger,那么就初始化一个,在启动框架前注册的话,就不会初始化了,可替换为其他 Logger
|
// 如果没有注册过 Logger,那么就初始化一个,在启动框架前注册的话,就不会初始化了,可替换为其他 Logger
|
||||||
$logger = new ConsoleLogger($config['log-level'] ?? $debug ?? 'info');
|
$logger = new ConsoleLogger($kernel->getLogLevel());
|
||||||
ob_logger_register($logger);
|
ob_logger_register($logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace ZM\Bootstrap;
|
namespace ZM\Bootstrap;
|
||||||
|
|
||||||
class SetInternalTimezone
|
use ZM\Kernel;
|
||||||
|
|
||||||
|
class SetInternalTimezone implements Bootstrapper
|
||||||
{
|
{
|
||||||
public function bootstrap(array $config): void
|
public function bootstrap(Kernel $kernel): void
|
||||||
{
|
{
|
||||||
date_default_timezone_set(config('global.runtime.timezone', 'UTC'));
|
date_default_timezone_set(config('global.runtime.timezone', 'UTC'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace ZM\Command\Server;
|
namespace ZM\Command\Server;
|
||||||
|
|
||||||
use OneBot\Driver\Process\ProcessManager;
|
use OneBot\Driver\Process\ProcessManager;
|
||||||
|
use OneBot\Driver\Workerman\Worker;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
@@ -26,13 +27,10 @@ class ServerStartCommand extends ServerCommand
|
|||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
$this->setDefinition([
|
$this->setDefinition([
|
||||||
new InputOption('config-dir', null, InputOption::VALUE_REQUIRED, '指定其他配置文件目录'),
|
|
||||||
new InputOption('driver', null, InputOption::VALUE_REQUIRED, '指定驱动类型'),
|
new InputOption('driver', null, InputOption::VALUE_REQUIRED, '指定驱动类型'),
|
||||||
new InputOption('log-level', null, InputOption::VALUE_REQUIRED, '调整消息等级到debug (log-level=4)'),
|
|
||||||
new InputOption('daemon', null, null, '以守护进程的方式运行框架'),
|
new InputOption('daemon', null, null, '以守护进程的方式运行框架'),
|
||||||
new InputOption('worker-num', null, InputOption::VALUE_REQUIRED, '启动框架时运行的 Worker 进程数量'),
|
new InputOption('worker-num', null, InputOption::VALUE_REQUIRED, '启动框架时运行的 Worker 进程数量'),
|
||||||
new InputOption('watch', null, null, '监听 plugins/ 目录下各个插件的文件变化并热更新(还不能用)'),
|
new InputOption('watch', null, null, '监听 plugins/ 目录下各个插件的文件变化并热更新(还不能用)'),
|
||||||
new InputOption('env', null, InputOption::VALUE_REQUIRED, '设置环境类型 (production, development, staging)'),
|
|
||||||
new InputOption('disable-safe-exit', null, null, '关闭安全退出(关闭后按CtrlC时直接杀死进程)'),
|
new InputOption('disable-safe-exit', null, null, '关闭安全退出(关闭后按CtrlC时直接杀死进程)'),
|
||||||
new InputOption('no-state-check', null, null, '关闭启动前框架运行状态检查'),
|
new InputOption('no-state-check', null, null, '关闭启动前框架运行状态检查'),
|
||||||
new InputOption('private-mode', null, null, '启动时隐藏MOTD和敏感信息'),
|
new InputOption('private-mode', null, null, '启动时隐藏MOTD和敏感信息'),
|
||||||
@@ -60,6 +58,21 @@ class ServerStartCommand extends ServerCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($input->getOption('driver')) {
|
||||||
|
config(['global.driver' => $input->getOption('driver')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($input->getOption('worker-num')) {
|
||||||
|
config(['global.swoole_options.swoole_set.worker_num' => (int) $input->getOption('worker-num')]);
|
||||||
|
config(['global.workerman_options.workerman_worker_num' => (int) $input->getOption('worker-num')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($input->getOption('daemon')) {
|
||||||
|
config(['global.swoole_options.swoole_set.daemonize' => 1]);
|
||||||
|
Worker::$daemonize = true;
|
||||||
|
}
|
||||||
|
|
||||||
// 框架启动的入口
|
// 框架启动的入口
|
||||||
(new Framework($input->getOptions()))->init()->start();
|
(new Framework($input->getOptions()))->init()->start();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use OneBot\Config\Config;
|
|||||||
use OneBot\Config\Loader\LoaderInterface;
|
use OneBot\Config\Loader\LoaderInterface;
|
||||||
use OneBot\Util\Singleton;
|
use OneBot\Util\Singleton;
|
||||||
use ZM\Exception\ConfigException;
|
use ZM\Exception\ConfigException;
|
||||||
|
use ZM\Kernel;
|
||||||
|
|
||||||
class ZMConfig
|
class ZMConfig
|
||||||
{
|
{
|
||||||
@@ -42,11 +43,6 @@ class ZMConfig
|
|||||||
*/
|
*/
|
||||||
private array $config_paths;
|
private array $config_paths;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string 当前环境
|
|
||||||
*/
|
|
||||||
private string $environment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Config 内部配置容器
|
* @var Config 内部配置容器
|
||||||
*/
|
*/
|
||||||
@@ -66,18 +62,15 @@ class ZMConfig
|
|||||||
/**
|
/**
|
||||||
* 构造配置实例
|
* 构造配置实例
|
||||||
*
|
*
|
||||||
* @param string $environment 环境
|
|
||||||
*
|
|
||||||
* @throws ConfigException 配置文件加载出错
|
* @throws ConfigException 配置文件加载出错
|
||||||
*/
|
*/
|
||||||
public function __construct(string $environment = 'uninitiated', array $init_config = null)
|
public function __construct(array $init_config = null)
|
||||||
{
|
{
|
||||||
$conf = $init_config ?: $this->loadInitConfig();
|
// 合并初始化配置,构造传入优先
|
||||||
|
$conf = array_merge_recursive($this->loadInitConfig(), $init_config ?? []);
|
||||||
$this->file_extensions = $conf['source']['extensions'];
|
$this->file_extensions = $conf['source']['extensions'];
|
||||||
$this->config_paths = $conf['source']['paths'];
|
$this->config_paths = $conf['source']['paths'];
|
||||||
|
|
||||||
$this->environment = self::$environment_alias[$environment] ?? $environment;
|
|
||||||
|
|
||||||
// 初始化配置容器
|
// 初始化配置容器
|
||||||
$this->holder = new Config(
|
$this->holder = new Config(
|
||||||
new ($conf['repository'][0])(...$conf['repository'][1]),
|
new ($conf['repository'][0])(...$conf['repository'][1]),
|
||||||
@@ -93,9 +86,7 @@ class ZMConfig
|
|||||||
$this->tracer = null;
|
$this->tracer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($environment !== 'uninitiated') {
|
$this->loadFiles();
|
||||||
$this->loadFiles();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -207,32 +198,6 @@ class ZMConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前环境
|
|
||||||
*
|
|
||||||
* @return string 当前环境
|
|
||||||
*/
|
|
||||||
public function getEnvironment(): string
|
|
||||||
{
|
|
||||||
return $this->environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置当前环境
|
|
||||||
*
|
|
||||||
* 变更环境后,将会自动调用 `reload` 方法重载配置
|
|
||||||
*
|
|
||||||
* @param string $environment 目标环境
|
|
||||||
*/
|
|
||||||
public function setEnvironment(string $environment): void
|
|
||||||
{
|
|
||||||
$target = self::$environment_alias[$environment] ?? $environment;
|
|
||||||
if ($this->environment !== $target) {
|
|
||||||
$this->environment = $target;
|
|
||||||
$this->reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重载配置文件
|
* 重载配置文件
|
||||||
* 运行期间新增的配置文件不会被加载哟~
|
* 运行期间新增的配置文件不会被加载哟~
|
||||||
@@ -337,7 +302,7 @@ class ZMConfig
|
|||||||
}
|
}
|
||||||
if ($type === 'environment') {
|
if ($type === 'environment') {
|
||||||
$name_and_env = explode('.', $name);
|
$name_and_env = explode('.', $name);
|
||||||
if ($name_and_env[1] === $this->environment) {
|
if (Kernel::getInstance()->environment($name_and_env[1])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ namespace ZM;
|
|||||||
use Symfony\Component\Console\Application;
|
use Symfony\Component\Console\Application;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
|
use Symfony\Component\Console\CommandLoader\FactoryCommandLoader;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\ConsoleEvents;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||||
use ZM\Command\Server\ServerStartCommand;
|
use Symfony\Component\Console\Event\ConsoleErrorEvent;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use ZM\Exception\SingletonViolationException;
|
use ZM\Exception\SingletonViolationException;
|
||||||
use ZM\Store\FileSystem;
|
use ZM\Store\FileSystem;
|
||||||
|
|
||||||
@@ -20,15 +22,6 @@ use ZM\Store\FileSystem;
|
|||||||
*/
|
*/
|
||||||
final class ConsoleApplication extends Application
|
final class ConsoleApplication extends Application
|
||||||
{
|
{
|
||||||
protected array $bootstrappers = [
|
|
||||||
Bootstrap\LoadConfiguration::class, // 加载配置文件
|
|
||||||
Bootstrap\LoadGlobalDefines::class, // 加载框架级别的全局常量声明
|
|
||||||
Bootstrap\RegisterLogger::class, // 加载 Logger
|
|
||||||
Bootstrap\HandleExceptions::class, // 注册异常处理器
|
|
||||||
Bootstrap\RegisterEventProvider::class, // 绑定框架的 EventProvider 到 libob 的 Driver 上
|
|
||||||
Bootstrap\SetInternalTimezone::class, // 设置时区
|
|
||||||
];
|
|
||||||
|
|
||||||
private static ?ConsoleApplication $obj = null;
|
private static ?ConsoleApplication $obj = null;
|
||||||
|
|
||||||
public function __construct(string $name = 'zhamao-framework')
|
public function __construct(string $name = 'zhamao-framework')
|
||||||
@@ -37,6 +30,67 @@ final class ConsoleApplication extends Application
|
|||||||
throw new SingletonViolationException(self::class);
|
throw new SingletonViolationException(self::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化 Composer 变量
|
||||||
|
if (file_exists(WORKING_DIR . '/runtime/composer.phar')) {
|
||||||
|
echo '* Using native composer' . PHP_EOL;
|
||||||
|
putenv('COMPOSER_EXECUTABLE=' . WORKING_DIR . '/runtime/composer.phar');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->registerCommandLoader();
|
||||||
|
|
||||||
|
// 执行父级初始化
|
||||||
|
parent::__construct($name, ZM_VERSION);
|
||||||
|
|
||||||
|
$this->registerGlobalOptions();
|
||||||
|
|
||||||
|
// 设置命令事件分发器
|
||||||
|
$dispatcher = new EventDispatcher();
|
||||||
|
$this->setDispatcher($dispatcher);
|
||||||
|
|
||||||
|
// 注册命令执行前监听器
|
||||||
|
$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
|
||||||
|
$input = $event->getInput();
|
||||||
|
|
||||||
|
// 初始化内核
|
||||||
|
/** @var Kernel $kernel */
|
||||||
|
$kernel = Kernel::getInstance();
|
||||||
|
$kernel->setConfigDir($input->getOption('config-dir'));
|
||||||
|
$kernel->setEnvironment($input->getOption('env'));
|
||||||
|
$kernel->setDebugMode($input->getOption('debug'));
|
||||||
|
$kernel->setLogLevel($input->getOption('log-level'));
|
||||||
|
$kernel->bootstrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 注册命令执行错误监听器
|
||||||
|
$dispatcher->addListener(ConsoleEvents::ERROR, function (ConsoleErrorEvent $event) {
|
||||||
|
$e = $event->getError();
|
||||||
|
// 输出错误信息
|
||||||
|
echo zm_internal_errcode('E00005') . "{$e->getMessage()} at {$e->getFile()}({$e->getLine()})" . PHP_EOL;
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设置单例,阻止后续实例化
|
||||||
|
self::$obj = $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册全局选项,应用到所有命令
|
||||||
|
*/
|
||||||
|
public function registerGlobalOptions(): void
|
||||||
|
{
|
||||||
|
$this->getDefinition()->addOptions([
|
||||||
|
new InputOption('debug', 'd', InputOption::VALUE_NONE, '启用调试模式'),
|
||||||
|
new InputOption('env', 'e', InputOption::VALUE_REQUIRED, '指定运行环境', 'development'),
|
||||||
|
new InputOption('config-dir', 'c', InputOption::VALUE_REQUIRED, '指定配置文件目录', SOURCE_ROOT_DIR . '/config'),
|
||||||
|
new InputOption('log-level', 'l', InputOption::VALUE_REQUIRED, '指定日志等级', 'info'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册命令加载器
|
||||||
|
*/
|
||||||
|
private function registerCommandLoader(): void
|
||||||
|
{
|
||||||
// 初始化命令
|
// 初始化命令
|
||||||
$command_classes = [];
|
$command_classes = [];
|
||||||
// 先加载框架内置命令
|
// 先加载框架内置命令
|
||||||
@@ -51,11 +105,7 @@ final class ConsoleApplication extends Application
|
|||||||
FileSystem::getClassesPsr4(SOURCE_ROOT_DIR . '/src/Command', 'Command')
|
FileSystem::getClassesPsr4(SOURCE_ROOT_DIR . '/src/Command', 'Command')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// 初始化 Composer 变量
|
// TODO: 加载插件命令,可以考虑自定义 CommandLoader
|
||||||
if (file_exists(WORKING_DIR . '/runtime/composer.phar')) {
|
|
||||||
echo '* Using native composer' . PHP_EOL;
|
|
||||||
putenv('COMPOSER_EXECUTABLE=' . WORKING_DIR . '/runtime/composer.phar');
|
|
||||||
}
|
|
||||||
$commands = [];
|
$commands = [];
|
||||||
foreach ($command_classes as $command_class) {
|
foreach ($command_classes as $command_class) {
|
||||||
try {
|
try {
|
||||||
@@ -78,27 +128,5 @@ final class ConsoleApplication extends Application
|
|||||||
// 命令工厂,用于延迟加载命令
|
// 命令工厂,用于延迟加载命令
|
||||||
$command_loader = new FactoryCommandLoader($commands);
|
$command_loader = new FactoryCommandLoader($commands);
|
||||||
$this->setCommandLoader($command_loader);
|
$this->setCommandLoader($command_loader);
|
||||||
|
|
||||||
self::$obj = $this; // 用于标记已经初始化完成
|
|
||||||
parent::__construct($name, ZM_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function run(InputInterface $input = null, OutputInterface $output = null): int
|
|
||||||
{
|
|
||||||
// 注册 bootstrap
|
|
||||||
$options = $input?->getOptions() ?? ServerStartCommand::exportOptionArray();
|
|
||||||
foreach ($this->bootstrappers as $bootstrapper) {
|
|
||||||
resolve($bootstrapper)->bootstrap($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return parent::run($input, $output);
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
echo zm_internal_errcode('E00005') . "{$e->getMessage()} at {$e->getFile()}({$e->getLine()})" . PHP_EOL;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ use DI;
|
|||||||
use DI\Container;
|
use DI\Container;
|
||||||
use DI\ContainerBuilder;
|
use DI\ContainerBuilder;
|
||||||
use OneBot\Driver\Coroutine\Adaptive;
|
use OneBot\Driver\Coroutine\Adaptive;
|
||||||
|
use ZM\Kernel;
|
||||||
|
|
||||||
class ContainerHolder
|
class ContainerHolder
|
||||||
{
|
{
|
||||||
/** @var Container[] */
|
/** @var Container[] */
|
||||||
private static array $container = [];
|
private static array $container = [];
|
||||||
|
|
||||||
|
private static array $config = [];
|
||||||
|
|
||||||
public static function getEventContainer(): Container
|
public static function getEventContainer(): Container
|
||||||
{
|
{
|
||||||
$cid = Adaptive::getCoroutine()?->getCid() ?? -1;
|
$cid = Adaptive::getCoroutine()?->getCid() ?? -1;
|
||||||
@@ -34,13 +37,13 @@ class ContainerHolder
|
|||||||
$builder = new ContainerBuilder();
|
$builder = new ContainerBuilder();
|
||||||
$builder->addDefinitions(
|
$builder->addDefinitions(
|
||||||
new AliasDefinitionSource(),
|
new AliasDefinitionSource(),
|
||||||
new DI\Definition\Source\DefinitionArray(config('container.definitions', [])),
|
new DI\Definition\Source\DefinitionArray(self::$config['definitions'] ?? []),
|
||||||
);
|
);
|
||||||
$builder->useAutowiring(true);
|
$builder->useAutowiring(true);
|
||||||
$builder->useAttributes(true);
|
$builder->useAttributes(true);
|
||||||
|
|
||||||
// 容器缓存
|
// 容器缓存
|
||||||
$enable_cache = config('container.cache.enable', false);
|
$enable_cache = self::$config['cache']['enable'] ?? false;
|
||||||
if (is_callable($enable_cache)) {
|
if (is_callable($enable_cache)) {
|
||||||
$enable_cache = $enable_cache();
|
$enable_cache = $enable_cache();
|
||||||
}
|
}
|
||||||
@@ -49,10 +52,15 @@ class ContainerHolder
|
|||||||
if (!extension_loaded('apcu')) {
|
if (!extension_loaded('apcu')) {
|
||||||
logger()->warning('APCu 扩展未加载,容器缓存将不可用');
|
logger()->warning('APCu 扩展未加载,容器缓存将不可用');
|
||||||
} else {
|
} else {
|
||||||
$builder->enableDefinitionCache(config('container.cache.namespace', ''));
|
$builder->enableDefinitionCache(self::$config['cache']['namespace'] ?? '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $builder->build();
|
return $builder->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function loadConfig(): void
|
||||||
|
{
|
||||||
|
self::$config = require Kernel::getInstance()->getConfigDir() . '/container.php';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ use OneBot\Driver\Workerman\Worker;
|
|||||||
use OneBot\Driver\Workerman\WorkermanDriver;
|
use OneBot\Driver\Workerman\WorkermanDriver;
|
||||||
use OneBot\Util\Singleton;
|
use OneBot\Util\Singleton;
|
||||||
use ZM\Command\Server\ServerStartCommand;
|
use ZM\Command\Server\ServerStartCommand;
|
||||||
use ZM\Config\ZMConfig;
|
|
||||||
use ZM\Container\ContainerBindingListener;
|
use ZM\Container\ContainerBindingListener;
|
||||||
use ZM\Event\Listener\HttpEventListener;
|
use ZM\Event\Listener\HttpEventListener;
|
||||||
use ZM\Event\Listener\ManagerEventListener;
|
use ZM\Event\Listener\ManagerEventListener;
|
||||||
@@ -260,7 +259,7 @@ class Framework
|
|||||||
// 打印工作目录
|
// 打印工作目录
|
||||||
$properties['working_dir'] = WORKING_DIR;
|
$properties['working_dir'] = WORKING_DIR;
|
||||||
// 打印环境信息
|
// 打印环境信息
|
||||||
$properties['environment'] = ZMConfig::getInstance()->getEnvironment();
|
$properties['environment'] = Kernel::getInstance()->environment();
|
||||||
// 打印驱动
|
// 打印驱动
|
||||||
$properties['driver'] = config('global.driver');
|
$properties['driver'] = config('global.driver');
|
||||||
// 打印logger显示等级
|
// 打印logger显示等级
|
||||||
|
|||||||
124
src/ZM/Kernel.php
Normal file
124
src/ZM/Kernel.php
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace ZM;
|
||||||
|
|
||||||
|
use OneBot\Util\Singleton;
|
||||||
|
use ZM\Bootstrap\Bootstrapper;
|
||||||
|
|
||||||
|
class Kernel
|
||||||
|
{
|
||||||
|
use Singleton;
|
||||||
|
|
||||||
|
private array $bootstrappers = [];
|
||||||
|
|
||||||
|
private string $config_dir;
|
||||||
|
|
||||||
|
private string $environment;
|
||||||
|
|
||||||
|
private bool $debug_mode;
|
||||||
|
|
||||||
|
private string $log_level;
|
||||||
|
|
||||||
|
private function __construct()
|
||||||
|
{
|
||||||
|
$this->registerBootstrappers([
|
||||||
|
Bootstrap\LoadConfiguration::class, // 加载配置文件
|
||||||
|
Bootstrap\LoadGlobalDefines::class, // 加载框架级别的全局常量声明
|
||||||
|
Bootstrap\RegisterLogger::class, // 加载 Logger
|
||||||
|
Bootstrap\HandleExceptions::class, // 注册异常处理器
|
||||||
|
Bootstrap\RegisterEventProvider::class, // 绑定框架的 EventProvider 到 libob 的 Driver 上
|
||||||
|
Bootstrap\SetInternalTimezone::class, // 设置时区
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取版本号
|
||||||
|
*/
|
||||||
|
public function version(): string
|
||||||
|
{
|
||||||
|
return ZM_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置文件目录
|
||||||
|
*/
|
||||||
|
public function getConfigDir(): string
|
||||||
|
{
|
||||||
|
return $this->config_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置配置文件目录
|
||||||
|
*/
|
||||||
|
public function setConfigDir(string $config_dir): void
|
||||||
|
{
|
||||||
|
$this->config_dir = $config_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取或检查运行环境
|
||||||
|
*
|
||||||
|
* @param array|string ...$environments
|
||||||
|
*/
|
||||||
|
public function environment(...$environments): string|bool
|
||||||
|
{
|
||||||
|
if (empty($environments)) {
|
||||||
|
return $this->environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
return in_array($this->environment, $environments, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置运行环境
|
||||||
|
*/
|
||||||
|
public function setEnvironment(string $environment): void
|
||||||
|
{
|
||||||
|
$this->environment = $environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDebugMode(): bool
|
||||||
|
{
|
||||||
|
return $this->debug_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDebugMode(bool $debug_mode): void
|
||||||
|
{
|
||||||
|
$this->debug_mode = $debug_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogLevel(): string
|
||||||
|
{
|
||||||
|
return $this->isDebugMode() ? 'debug' : $this->log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLogLevel(string $log_level): void
|
||||||
|
{
|
||||||
|
$this->log_level = $log_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runningInConsole(): bool
|
||||||
|
{
|
||||||
|
return PHP_SAPI === 'cli';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runningUnitTests(): bool
|
||||||
|
{
|
||||||
|
return $this->environment('testing');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function registerBootstrappers(array $bootstrappers): void
|
||||||
|
{
|
||||||
|
$this->bootstrappers = array_merge($this->bootstrappers, $bootstrappers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bootstrap(): void
|
||||||
|
{
|
||||||
|
foreach ($this->bootstrappers as $bootstrapper) {
|
||||||
|
/* @var Bootstrapper $bootstrapper */
|
||||||
|
(new $bootstrapper())->bootstrap($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user