From aa29dc99f3416a1cde33b247b083d8c54f9ca960 Mon Sep 17 00:00:00 2001 From: sunxyw Date: Tue, 8 Nov 2022 17:28:07 +0800 Subject: [PATCH 1/3] orgianze bootstrapper --- src/Globals/global_functions.php | 10 +- src/ZM/Bootstrap/HandleExceptions.php | 35 +++++++ src/ZM/Bootstrap/LoadConfiguration.php | 69 ++++++++++++++ src/ZM/Bootstrap/LoadGlobalDefines.php | 11 +++ src/ZM/Bootstrap/RegisterEventProvider.php | 14 +++ src/ZM/Bootstrap/RegisterLogger.php | 18 ++++ src/ZM/Bootstrap/SetInternalTimezone.php | 11 +++ src/ZM/Exception/Handler.php | 31 ++++++ src/ZM/Framework.php | 104 ++++----------------- 9 files changed, 210 insertions(+), 93 deletions(-) create mode 100644 src/ZM/Bootstrap/HandleExceptions.php create mode 100644 src/ZM/Bootstrap/LoadConfiguration.php create mode 100644 src/ZM/Bootstrap/LoadGlobalDefines.php create mode 100644 src/ZM/Bootstrap/RegisterEventProvider.php create mode 100644 src/ZM/Bootstrap/RegisterLogger.php create mode 100644 src/ZM/Bootstrap/SetInternalTimezone.php create mode 100644 src/ZM/Exception/Handler.php diff --git a/src/Globals/global_functions.php b/src/Globals/global_functions.php index a7288823..1d5555ec 100644 --- a/src/Globals/global_functions.php +++ b/src/Globals/global_functions.php @@ -143,7 +143,7 @@ function container(): ContainerInterface * 解析类实例(使用容器) * * @template T - * @param class-string $abstract + * @param class-string $abstract * @return Closure|mixed|T * @noinspection PhpDocMissingThrowsInspection */ @@ -157,7 +157,7 @@ function resolve(string $abstract, array $parameters = []) * 获取容器实例 * * @template T - * @param null|class-string $abstract + * @param null|class-string $abstract * @return Closure|ContainerInterface|mixed|T */ function app(string $abstract = null, array $parameters = []) @@ -196,11 +196,11 @@ function sql_builder(string $name = '') * 传入数组,设置配置项 * 不传参数,返回配置容器 * - * @param null|array|string $key 键名 - * @param mixed $default 默认值 + * @param array|string|null $key 键名 + * @param mixed|null $default 默认值 * @return mixed|void|ZMConfig */ -function config($key = null, $default = null) +function config(array|string $key = null, mixed $default = null) { $config = ZMConfig::getInstance(); if (is_null($key)) { diff --git a/src/ZM/Bootstrap/HandleExceptions.php b/src/ZM/Bootstrap/HandleExceptions.php new file mode 100644 index 00000000..99bc4571 --- /dev/null +++ b/src/ZM/Bootstrap/HandleExceptions.php @@ -0,0 +1,35 @@ + ['PHP Warning: ', 'warning'], + E_NOTICE => ['PHP Notice: ', 'notice'], + E_USER_ERROR => ['PHP Error: ', 'error'], + E_USER_WARNING => ['PHP Warning: ', 'warning'], + E_USER_NOTICE => ['PHP Notice: ', 'notice'], + E_STRICT => ['PHP Strict: ', 'notice'], + E_RECOVERABLE_ERROR => ['PHP Recoverable Error: ', 'error'], + E_DEPRECATED => ['PHP Deprecated: ', 'notice'], + E_USER_DEPRECATED => ['PHP User Deprecated: ', 'notice'], + ]; + $level_tip = $tips[$error_no] ?? ['PHP Unknown: ', 'error']; + $error = $level_tip[0] . $error_msg . ' in ' . $error_file . ' on ' . $error_line; + logger()->{$level_tip[1]}($error); + // 如果 return false 则错误会继续递交给 PHP 标准错误处理 + return true; + }, E_ALL | E_STRICT); + + // 重载异常处理器 + ExceptionHandler::getInstance()->overrideWith(new Handler()); + } +} diff --git a/src/ZM/Bootstrap/LoadConfiguration.php b/src/ZM/Bootstrap/LoadConfiguration.php new file mode 100644 index 00000000..8ab2b90d --- /dev/null +++ b/src/ZM/Bootstrap/LoadConfiguration.php @@ -0,0 +1,69 @@ +addConfigPath($this->getConfigDir($config)); + $config_i->setEnvironment($this->getConfigEnvironment($config)); + $this->parseArgvToConfig($config, $config_i); + } + + private function getConfigDir(array $config): string + { + $config_dir = $config['config-dir']; + // 默认配置文件目录 + $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; + } + } + } +} diff --git a/src/ZM/Bootstrap/LoadGlobalDefines.php b/src/ZM/Bootstrap/LoadGlobalDefines.php new file mode 100644 index 00000000..36cc47c1 --- /dev/null +++ b/src/ZM/Bootstrap/LoadGlobalDefines.php @@ -0,0 +1,11 @@ +whoops)) { + ob_logger()->error('Uncaught ' . get_class($e) . ': ' . $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')'); + ob_logger()->error($e->getTraceAsString()); + return; + } + +// $this->whoops->handleException($e); + } +} diff --git a/src/ZM/Framework.php b/src/ZM/Framework.php index 0868fc75..087b674f 100644 --- a/src/ZM/Framework.php +++ b/src/ZM/Framework.php @@ -33,6 +33,7 @@ use ZM\Exception\ZMKnownException; use ZM\Logger\ConsoleLogger; use ZM\Logger\TablePrinter; use ZM\Process\ProcessStateManager; +use ZM\Bootstrap; /** * 框架入口类 @@ -57,10 +58,20 @@ class Framework /** @var array> 启动注解列表 */ protected array $setup_annotations = []; + protected array $bootstrappers = [ + // 驱动前置 + Bootstrap\LoadConfiguration::class, + Bootstrap\LoadGlobalDefines::class, + Bootstrap\RegisterLogger::class, + Bootstrap\HandleExceptions::class, + Bootstrap\RegisterEventProvider::class, + Bootstrap\SetInternalTimezone::class, + ]; + /** * 框架初始化文件 * - * @param array $argv 传入的参数(见 ServerStartCommand) + * @param array $argv 传入的参数(见 ServerStartCommand) * @throws InitException * @throws \Exception */ @@ -81,6 +92,10 @@ class Framework */ public function init(): Framework { + foreach ($this->bootstrappers as $bootstrapper) { + app($bootstrapper)->bootstrap($this->argv); + } + // 执行一些 Driver 前置条件的内容 $this->initDriverPrerequisites(); @@ -177,70 +192,9 @@ class Framework * 6. 覆盖 PHP 报错样式解析 * 7. 解析命令行参数 * 8. 读取、解析并执行 OnSetup 注解 - * - * @throws ConfigException */ public function initDriverPrerequisites() { - // 寻找配置文件目录 - if ($this->argv['config-dir'] !== null) { // 如果启动参数指定了config寻找目录,那么就在指定的寻找,不在别的地方寻找了 - $find_dir = [$this->argv['config-dir']]; - logger()->debug('使用命令参数指定的config-dir:' . $this->argv['config-dir']); - } else { // 否则就从默认的工作目录或源码根目录寻找 - $find_dir = [WORKING_DIR . '/config', SOURCE_ROOT_DIR . '/config']; - } - foreach ($find_dir as $v) { - if (is_dir($v)) { - config()->addConfigPath($v); - config()->setEnvironment($this->argv['env'] = ($this->argv['env'] ?? 'development')); - $config_done = true; - break; - } - } - // 找不到的话直接崩溃,因为框架依赖全局配置文件(但其实这个错误在 3.0 开始应该永远无法执行到) - if (!isset($config_done)) { - echo zm_internal_errcode('E00007') . 'Global config load failed' . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n"; - exit(1); - } - - // 初始化框架本体运行需要的常量,比如运行时间等 - require zm_dir(__DIR__ . '/../Globals/global_defines_framework.php'); - - // 初始化 Logger,此处为 Master 进程第一次初始化,在后续的多进程环境下,还需要在 Worker 进程中初始化 - if (!ob_logger_registered()) { // 如果没有注册过 Logger,那么就初始化一个,在启动框架前注册的话,就不会初始化了,可替换为其他 Logger - ob_logger_register(new ConsoleLogger($this->argv['log-level'] ?? 'info')); - } - - // 注册自己的EventProvider - global $ob_event_provider; - $ob_event_provider = EventProvider::getInstance(); - - // 初始化时区,默认为上海时区 - date_default_timezone_set(config('global.runtime.timezone')); - - // 注册全局错误处理器 - set_error_handler(static function ($error_no, $error_msg, $error_file, $error_line) { - $tips = [ - E_WARNING => ['PHP Warning: ', 'warning'], - E_NOTICE => ['PHP Notice: ', 'notice'], - E_USER_ERROR => ['PHP Error: ', 'error'], - E_USER_WARNING => ['PHP Warning: ', 'warning'], - E_USER_NOTICE => ['PHP Notice: ', 'notice'], - E_STRICT => ['PHP Strict: ', 'notice'], - E_RECOVERABLE_ERROR => ['PHP Recoverable Error: ', 'error'], - E_DEPRECATED => ['PHP Deprecated: ', 'notice'], - E_USER_DEPRECATED => ['PHP User Deprecated: ', 'notice'], - ]; - $level_tip = $tips[$error_no] ?? ['PHP Unknown: ', 'error']; - $error = $level_tip[0] . $error_msg . ' in ' . $error_file . ' on ' . $error_line; - logger()->{$level_tip[1]}($error); - // 如果 return false 则错误会继续递交给 PHP 标准错误处理 - return true; - }, E_ALL | E_STRICT); - - // 解析命令行参数 - $this->parseArgs(); - // 初始化 @OnSetup 事件 $this->initSetupAnnotations(); } @@ -459,32 +413,6 @@ class Framework echo $motd; } - /** - * 解析 argv 参数 - */ - private function parseArgs() - { - foreach ($this->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', intval($y)); - config()->set('global.workerman_options.workerman_worker_num', intval($y)); - break; - case 'daemon': // 启动为守护进程 - config()->set('global.swoole_options.swoole_set.daemonize', 1); - Worker::$daemonize = true; - break; - } - } - } - /** * 初始化 OnSetup 注解 */ From 723dfd30a26ade2f1182d7c9711da3345c214586 Mon Sep 17 00:00:00 2001 From: sunxyw Date: Tue, 8 Nov 2022 17:33:25 +0800 Subject: [PATCH 2/3] fix styles --- src/Globals/global_functions.php | 8 ++++---- src/ZM/Bootstrap/HandleExceptions.php | 2 ++ src/ZM/Bootstrap/LoadConfiguration.php | 6 ++++-- src/ZM/Bootstrap/LoadGlobalDefines.php | 2 ++ src/ZM/Bootstrap/RegisterEventProvider.php | 2 ++ src/ZM/Bootstrap/RegisterLogger.php | 2 ++ src/ZM/Bootstrap/SetInternalTimezone.php | 2 ++ src/ZM/Exception/Handler.php | 5 +++-- src/ZM/Framework.php | 5 +---- 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Globals/global_functions.php b/src/Globals/global_functions.php index 1d5555ec..c6554ae3 100644 --- a/src/Globals/global_functions.php +++ b/src/Globals/global_functions.php @@ -143,7 +143,7 @@ function container(): ContainerInterface * 解析类实例(使用容器) * * @template T - * @param class-string $abstract + * @param class-string $abstract * @return Closure|mixed|T * @noinspection PhpDocMissingThrowsInspection */ @@ -157,7 +157,7 @@ function resolve(string $abstract, array $parameters = []) * 获取容器实例 * * @template T - * @param null|class-string $abstract + * @param null|class-string $abstract * @return Closure|ContainerInterface|mixed|T */ function app(string $abstract = null, array $parameters = []) @@ -196,8 +196,8 @@ function sql_builder(string $name = '') * 传入数组,设置配置项 * 不传参数,返回配置容器 * - * @param array|string|null $key 键名 - * @param mixed|null $default 默认值 + * @param null|array|string $key 键名 + * @param null|mixed $default 默认值 * @return mixed|void|ZMConfig */ function config(array|string $key = null, mixed $default = null) diff --git a/src/ZM/Bootstrap/HandleExceptions.php b/src/ZM/Bootstrap/HandleExceptions.php index 99bc4571..709552d3 100644 --- a/src/ZM/Bootstrap/HandleExceptions.php +++ b/src/ZM/Bootstrap/HandleExceptions.php @@ -1,5 +1,7 @@ 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); + $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); diff --git a/src/ZM/Bootstrap/LoadGlobalDefines.php b/src/ZM/Bootstrap/LoadGlobalDefines.php index 36cc47c1..1c1b45ea 100644 --- a/src/ZM/Bootstrap/LoadGlobalDefines.php +++ b/src/ZM/Bootstrap/LoadGlobalDefines.php @@ -1,5 +1,7 @@ $argv 传入的参数(见 ServerStartCommand) + * @param array $argv 传入的参数(见 ServerStartCommand) * @throws InitException * @throws \Exception */ From 02003b2bd32bf6e7532394f9de94eee3982e260d Mon Sep 17 00:00:00 2001 From: sunxyw Date: Sat, 12 Nov 2022 01:15:40 +0800 Subject: [PATCH 3/3] reduce useless method --- src/ZM/Framework.php | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/ZM/Framework.php b/src/ZM/Framework.php index d75925bd..551b767e 100644 --- a/src/ZM/Framework.php +++ b/src/ZM/Framework.php @@ -89,12 +89,13 @@ class Framework */ public function init(): Framework { + // 顺序执行引导器 foreach ($this->bootstrappers as $bootstrapper) { app($bootstrapper)->bootstrap($this->argv); } - // 执行一些 Driver 前置条件的内容 - $this->initDriverPrerequisites(); + // 初始化 @OnSetup 事件 + $this->initSetupAnnotations(); // 初始化 Driver 及框架内部需要监听的事件 $this->initDriver(); @@ -178,24 +179,6 @@ class Framework return $this->driver; } - /** - * 在框架的 Driver 层初始化前的一些前提条件 - * - * 1. 设置 config 读取的目录 - * 2. 初始化框架运行时的常量 - * 3. 初始化 Logger - * 4. 初始化 EventProvider - * 5. 设置时区,防止 Logger 时间乱跳 - * 6. 覆盖 PHP 报错样式解析 - * 7. 解析命令行参数 - * 8. 读取、解析并执行 OnSetup 注解 - */ - public function initDriverPrerequisites() - { - // 初始化 @OnSetup 事件 - $this->initSetupAnnotations(); - } - /** * 初始化驱动及相关事件 * 实例化 Driver 对象