乐趣区

关于php:从binswoft开始阅读Swoft框架源码一Application的初始化

bean/swoft中的代码如下:

// 引入 bootstrap.php 文件
// 实际上 bootstrap.php 只干了一件事: 引入 /vendor/autoload.php
// 由 autoload.php 来加载我的项目中的库类
// Bootstrap
require_once __DIR__ . '/bootstrap.php';

// 设置最大协程数量
SwooleCoroutine::set(['max_coroutine' => 300000,]);

// 实例化 application
// 调用 application 的 run 办法执行利用
// run 办法申明在 Swoft\Contract\ApplicationInterface
// 实现在 Swoft\SwoftApplication
// Run application
(new AppApplication())->run();

AppApplication 的实现很简略:

class Application extends SwoftApplication
{protected function beforeInit(): void
     {parent::beforeInit();
         
         // 设置时区
         // you can init php setting.
         date_default_timezone_set('Asia/Shanghai');
     }
     /**
     * @return array
     */ public function getCLoggerConfig(): array
     {$config = parent::getCLoggerConfig();
         // False: Dont print log to terminal
         // 将控制台输入关上
         $config['enable'] = true;
         return $config;
     }
}

外面只是重写了父类 SwoftApplication 的 beforeInit 办法和`
getCLoggerConfig 办法.

所以实例化 application 的操作还是在父类 SwoftApplication 的构造方法中实现的, 先看父类的构造方法代码:

public function __construct(array $config = [])
{
     // 第一件事件是查看以后的运行环境
     // 后附查看运行时环境的代码
     // 次要检测 PHP 版本、swoole 版本以及是否加载了有抵触的扩大
     // Check runtime env
     SwoftHelper::checkRuntime();
     
     // Storage as global static property.
     // 将以后实例保留在 Swoft 类的动态属性上
     Swoft::$app = $this;
     
     // 调用(触发)beforeInit 函数(事件)
     // 在 Application 的 beforeInit 中先调用了父类的 beforeInit
     // 父类中检测并定义了是否在 Phar 包中执行的常量 IN_PHAR
     // 而后子类中设置了以后时区
     // Before init
     $this->beforeInit();
     
     
     // 初始化控制台日志 logger
     // 后附日志初始化代码
     // Init console logger
     $this->initCLogger();
     
     // 设置额定属性 此处因为未传结构参数 所以不会执行
     // Can setting properties by array
     if ($config) {ObjectHelper::init($this, $config);
     }
     
     // 初始化利用
     // 后附实现代码
     // Init application
     $this->init();
     
     // afterInit 办法 (事件) 调用(触发)
     // 如果是在 phar 环境上面会设置 runtime 目录, 未做其它额定操作
     // After init
     $this->afterInit();}

运行时环境检测代码:

public static function checkRuntime(string $minPhp = '7.1', string $minSwoole = '4.4.1'): void
{
     // 检测 php 版本是否大于 7.1 不满足条件就抛出 RuntimeException
     if (version_compare(PHP_VERSION, $minPhp, '<')) {throw new RuntimeException('Run the server requires PHP version >' . $minPhp . '! current is' . PHP_VERSION);
     }
     
     // 检测是否加载了 swoole 扩大 
     if (!extension_loaded('swoole')) {throw new RuntimeException("Run the server, extension'swoole'is required!");
     }
     
     // 检测 swoole 扩大版本是否大于 4.4.1
     if (version_compare(SWOOLE_VERSION, $minSwoole, '<')) {throw new RuntimeException('Run the server requires swoole version >' . $minSwoole . '! current is' . SWOOLE_VERSION);
     }
     
     // 抵触扩大
     $conflicts = [
         'blackfire',
         'xdebug',
         'uopz',
         'xhprof',
         'zend',
         'trace',
     ];
     
     // 遍历抵触扩大 如果检测到加载了这些抵触扩大 则抛出异样
     foreach ($conflicts as $ext) {if (extension_loaded($ext)) {throw new RuntimeException("The extension of'{$ext}'must be closed, otherwise swoft will be affected!");
         }
     }
 }

SwoftApplication 的 beforeInit:

protected function beforeInit(): void
{
     // Check phar env
     // 检测运行环境是否为 phar 包
     if (!defined('IN_PHAR')) {define('IN_PHAR', false);
     }
}

日志初始化代码:

private function initCLogger(): void
{// 获取日志配置(此处为父类的返回) 
     // [
     //     'name' => 'swoft',
     //     'enable' => true,
     //     'output' => true,
     //     'levels' => '',
     //     'logFile' => ''
     // ]
     // Console logger config
     // 子类中再次将 enable 设置为 true
     $config = $this->getCLoggerConfig();
     
     // 初始化控制台 logger
     // swoft 的 CLog 应用 monolog, 在 monolog 的根底上
     // 封装了 getTrace 办法, 不便 swoole 的调试
     // 后附代码
     // Init console log
     CLog::init($config);
}

CLog::init 代码:

public static function init(array $config): void
{
     // self::$cLogger 不为 null 示意曾经有 logger, 无需再次初始化
     if (self::$cLogger !== null) {return;}
     
     // config 配置
     $name = $config['name'] ?? '';
     $enable = $config['enable'] ?? true;
     $output = $config['output'] ?? true;
     $levels = $config['levels'] ?? '';
     $logFile = $config['logFile'] ?? '';
     
     // 此处应用 monolog 的 LineFormatter 作为后续
     // CEchoHandler 和 CFileHandler 的组件
     $lineFormatter = new LineFormatter();
     
     // 初始化 CEchoHandler 并设置
     $cEchoHandler = new CEchoHandler();
     $cEchoHandler->setFormatter($lineFormatter);
     $cEchoHandler->setLevels($levels);
     $cEchoHandler->setOutput($output);
     
     // 初始化 CFileHandler 并设置
     $cFileHandler = new CFileHandler();
     $cFileHandler->setFormatter($lineFormatter);
     $cFileHandler->setLevels($levels);
     $cFileHandler->setLogFile($logFile);
     
     // 初始化 CLogger 该 logger 继承于 monolog
     $cLogger = new CLogger();
     $cLogger->setName($name);
     $cLogger->setEnable($enable);
     $cLogger->setHandlers([$cEchoHandler, $cFileHandler]);
     
     // 将初始化好的控制台 logger 保留在 cLogger 属性上
     self::$cLogger = $cLogger;
}

Application 的初始化:

protected function init(): void
{
     // Init system path aliases
     
     // 设置根底门路(我的项目根目录)
     $this->findBasePath();
     
     // 设置并打印 @base@app@config@runtime 的门路别名
     $this->setSystemAlias();
     
     // 初始化 EnvProcessor、ConfigProcessor、AnnotationProcessor
     // BeanProcessor、EventProcessor、ConsoleProcessor
     // 此 6 个处理器内容太多且只是初始化 后续章节理论调用时将阐明
     $processors = $this->processors();
     
     // 初始化以后利用的处理器
     $this->processor = new ApplicationProcessor($this);
     
     // 将后面初始化的处理器交给以后利用处理器对立治理调度
     $this->processor->addFirstProcessor(...$processors);
}

总结:

Application 初始化程序:
1. 查看运行时环境.
2. 触发初始化前事件.
3. 初始化控制台 logger.
4. 初始化利用.
5. 触发初始化后事件.
退出移动版