Starting from bin / swoft, read the source code of swoft framework (1) — initialization of application

Time:2021-3-26

bean/swoftThe code in is as follows:

//Introduction bootstrap.php file
//In fact bootstrap.php Only one thing: introduce / vendor/ autoload.php
//By autoload.php To load library classes in a project
// Bootstrap
require_once __DIR__ . '/bootstrap.php';

//Set the maximum number of coroutines
SwooleCoroutine::set([
 'max_coroutine' => 300000,
]);

//Instantiate application
//Call the run method of application to execute the application
//The run method is declared in the
//Implementation in swoft / swoftapplication
// Run application
(new AppApplication())->run();

The implementation of appapplication is very simple

class Application extends SwoftApplication
{
     protected function beforeInit(): void
     {
         parent::beforeInit();
         
         //Set time zone
         // 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
         //Turn the console output on
         $config['enable'] = true;
         return $config;
     }
}

It just rewrites the beforeinit method and the`
Getcloggerconfig method

Therefore, the operation of instantiating application is completed in the construction method of the parent class swoftapplication. First, look at the construction method code of the parent class

public function __construct(array $config = [])
{
     //The first thing is to examine the current operating environment
     //Attached is the code for checking the runtime environment
     //It mainly detects PHP version, spool version and whether conflicting extensions are loaded
     // Check runtime env
     SwoftHelper::checkRuntime();
     
     // Storage as global static property.
     //Save the current instance on the static property of the swoft class
     Swoft::$app = $this;
     
     //Call (trigger) the beforeinit function (event)
     //In the beforeinit of application, the beforeinit of the parent class is called first
     //A constant in that detects and defines whether to execute in phar package_ PHAR
     //Then the current time zone is set in the subclass
     // Before init
     $this->beforeInit();
     
     
     //Initialize console log logger
     //Attached log initialization code
     // Init console logger
     $this->initCLogger();
     
     //Set extra properties here because no construction parameters are passed, so it will not be executed
     // Can setting properties by array
     if ($config) {
        ObjectHelper::init($this, $config);
     }
     
     //Initialize application
     //The implementation code is attached
     // Init application
     $this->init();
     
     //Afterinit method (event) call (trigger)
     //If it is in phar environment, the runtime directory will be set, and no additional operation will be done
     // After init
     $this->afterInit();
}

Runtime environment detection code:

public static function checkRuntime(string $minPhp = '7.1', string $minSwoole = '4.4.1'): void
{
     //Check whether the PHP version is greater than 7.1 and throw runtimeException if the condition is not met
     if (version_compare(PHP_VERSION, $minPhp, '<')) {
        throw new RuntimeException('Run the server requires PHP version > ' . $minPhp . '! current is ' . PHP_VERSION);
     }
     
     //Check whether the spool extension is loaded 
     if (!extension_loaded('swoole')) {
        throw new RuntimeException("Run the server, extension 'swoole' is required!");
     }
     
     //Check whether the extended version of spool is greater than 4.4.1
     if (version_compare(SWOOLE_VERSION, $minSwoole, '<')) {
        throw new RuntimeException('Run the server requires swoole version > ' . $minSwoole . '! current is ' . SWOOLE_VERSION);
     }
     
     //Conflict expansion
     $conflicts = [
         'blackfire',
         'xdebug',
         'uopz',
         'xhprof',
         'zend',
         'trace',
     ];
     
     //Traversing conflicting extensions throws an exception if it detects that these conflicting extensions are loaded
     foreach ($conflicts as $ext) {
         if (extension_loaded($ext)) {
            throw new RuntimeException("The extension of '{$ext}' must be closed, otherwise swoft will be affected!");
         }
     }
 }

Before init of swoftapplication:

protected function beforeInit(): void
{
     // Check phar env
     //Check whether the running environment is phar package
     if (!defined('IN_PHAR')) {
        define('IN_PHAR', false);
     }
}

Log initialization code:

private function initCLogger(): void
{
     //Get log configuration (here is the return of parent class) 
     // [
     //     'name' => 'swoft',
     //     'enable' => true,
     //     'output' => true,
     //     'levels' => '',
     //     'logFile' => ''
     // ]
     // Console logger config
     //Set enable to true again in subclass
     $config = $this->getCLoggerConfig();
     
     //Initialize console logger
     //Sloft's clog uses monolog
     //The gettrace method is encapsulated to facilitate the debugging of spool
     //Code attached
     // Init console log
     CLog::init($config);
}

Clog:: init Code:

public static function init(array $config): void
{
     //If self:: $clogger is not null, it means that there is already a logger and there is no need to initialize it again
     if (self::$cLogger !== null) {
        return;
     }
     
     //Config configuration
     $name = $config['name'] ?? '';
     $enable = $config['enable'] ?? true;
     $output = $config['output'] ?? true;
     $levels = $config['levels'] ?? '';
     $logFile = $config['logFile'] ?? '';
     
     //The line formatter of monolog is used here as a follow-up
     //Components of cechohandler and cfilehandler
     $lineFormatter = new LineFormatter();
     
     //Initialize cechohandler and set
     $cEchoHandler = new CEchoHandler();
     $cEchoHandler->setFormatter($lineFormatter);
     $cEchoHandler->setLevels($levels);
     $cEchoHandler->setOutput($output);
     
     //Initialize cfilehandler and set
     $cFileHandler = new CFileHandler();
     $cFileHandler->setFormatter($lineFormatter);
     $cFileHandler->setLevels($levels);
     $cFileHandler->setLogFile($logFile);
     
     //Initializes the clogger, which inherits from the monolog
     $cLogger = new CLogger();
     $cLogger->setName($name);
     $cLogger->setEnable($enable);
     $cLogger->setHandlers([$cEchoHandler, $cFileHandler]);
     
     //Save the initialized console logger on the chlogger property
     self::$cLogger = $cLogger;
}

Initialization of application:

protected function init(): void
{
     // Init system path aliases
     
     //Set base path (project root)
     $this->findBasePath();
     
     //Set up and [email protected] [email protected]@[email protected] Path alias for
     $this->setSystemAlias();
     
     //Initialize envprocessor, configprocessor and annotationprocessor
     // BeanProcessor、EventProcessor、ConsoleProcessor
     //The contents of these six processors are too much, and they are only used to initialize, which will be explained in the actual call in the following chapters
     $processors = $this->processors();
     
     //Initializes the processor of the current application
     $this->processor = new ApplicationProcessor($this);
     
     //Give the previously initialized processor to the current application processor for unified management and scheduling
     $this->processor->addFirstProcessor(...$processors);
}

Conclusion:

Application initialization order:
1. Check the runtime environment
2. Trigger pre initialization event
3. Initialize the console logger
4. Initialize the application
5. Trigger post initialization event

Recommended Today

Deeply analyze the principle and practice of RSA key

1、 Preface After experiencing many dark moments in life, when you read this article, you will regret and even be angry: why didn’t you write this article earlier?! Your darkest moments include: 1. Your project needs to be connected with the bank, and the other party needs you to provide an encryption certificate. You have […]