美文网首页
Easyswoole源码分析-3-Install

Easyswoole源码分析-3-Install

作者: 会长__ | 来源:发表于2019-05-25 23:39 被阅读0次
    image.png

    1.简介

    下载Easyswoole框架后,需要执行php vendor/bin/easyswoole install,接下来介绍一些执行这个命令后具体执行了哪些操作。

    image.png

    2. 先看CommandRunner类的run方法

    核心代码

    function run(array $args):?string
        {
            ·
            ·
            ·
            // 如果执行命令为install
            }else if($command != 'install'){
                //预先加载配置(dev为线上配置,produce为开发配置)
                if(in_array('produce',$args)){
                    Core::getInstance()->setIsDev(false);
                }
                // 主要完成的操作1
                Core::getInstance()->initialize();
            }
            ·
            ·
            ·
            // 主要完成的操作2(请先阅读前几章)
            return CommandContainer::getInstance()->hook($command,$args);
        }
    

    1.根据install去执行相应操作。
    2.根据是否有produce参数来决定是否使用开发|线上配置。
    3.执行install类的exec方法。

    接下来具体来分析一下代码注释中的操作1和操作2

    3.Core::getInstance()->initialize();

    知识点

    1. ReflectionClass (反射机制)
    2. 类名|接口名|组合名::class
    3. php7的异常和错误的改变
    4. php spl 扩展的ArrayObject
      5.php预定义常量
      6.设计模式:适配器模式

    核心代码

    function initialize()
    {
            //检查全局文件是否存在.
            $file = EASYSWOOLE_ROOT . '/EasySwooleEvent.php';
            if(file_exists($file)){
                require_once $file;
                try{
                    $ref = new \ReflectionClass('EasySwoole\EasySwoole\EasySwooleEvent');
                    if(!$ref->implementsInterface(Event::class)){
                        die('global file for EasySwooleEvent is not compatible for EasySwoole\EasySwoole\EasySwooleEvent');
                    }
                    unset($ref);
                }catch (\Throwable $throwable){
                    die($throwable->getMessage());
                }
            }else{
                die('global event file missing');
            }
            //先加载配置文件
            $this->loadEnv();
            //执行了业务处理类的initialize方法
            EasySwooleEvent::initialize();
            //临时文件和Log目录初始化
            $this->sysDirectoryInit();
            //注册错误回调
            $this->registerErrorHandler();
            return $this;
    }
    

    接口是否实现

    //检查全局文件是否存在.
    $file = EASYSWOOLE_ROOT . '/EasySwooleEvent.php';
    if(file_exists($file)){
         require_once $file;
         try{
              $ref = new \ReflectionClass('EasySwoole\EasySwoole\EasySwooleEvent');
              if(!$ref->implementsInterface(Event::class)){
                    die('global file for EasySwooleEvent is not compatible for EasySwoole\EasySwoole\EasySwooleEvent');
              }
              unset($ref);
             }catch (\Throwable $throwable){
                  die($throwable->getMessage());
             }
    }else{
          // 如果没有EasySwooleEvent.php 直接die
          die('global event file missing');
    }
    

    loadEnv方法

    public function loadEnv()
        {
            //加载之前,先清空原来的
            if($this->isDev){
                $file  = EASYSWOOLE_ROOT.'/dev.php';
            }else{
                $file  = EASYSWOOLE_ROOT.'/produce.php';
            }
            Config::getInstance()->loadEnv($file);
        }
    

    Config的loadEnv方法

    /**
    * $this->conf = new SplArray(); 这里有时间会单独剖析一下一峰大佬写的
    * SplArray工具类,这个类继承了spl扩展的ArrayObject,看下上面的知识点应该就能看懂。
    *
    **/
    public function loadEnv(string $file)
    {
            if(file_exists($file)){
                $data = require $file;
                // 将ArrayObject对象给conf
                $this->conf->loadArray($data);
            }else{
                throw new \Exception("config file : {$file} is miss");
            }
    }
    

    $this->sysDirectoryInit();

    我再注释当中解释了过程

    private function sysDirectoryInit():void
        {
            //--------------------------------1.创建temp目录-------------------------------
            //创建临时目录    请以绝对路径,不然守护模式运行会有问题
            $tempDir = Config::getInstance()->getConf('TEMP_DIR');
            // 是否具有此配置项
            if(empty($tempDir)){
                // 没有配置则默认路径
                $tempDir = EASYSWOOLE_ROOT.'/Temp';
                // 设置默认路径
                Config::getInstance()->setConf('TEMP_DIR',$tempDir);
            }else{
                // 如果最后一个字符为/则删除
                $tempDir = rtrim($tempDir,'/');
            }
            if(!is_dir($tempDir)){
                // 创建目录
                mkdir($tempDir);
            }
            defined('EASYSWOOLE_TEMP_DIR') or define('EASYSWOOLE_TEMP_DIR',$tempDir);
            //---------------------------------2.创建Log目录------------------------------
            $logDir = Config::getInstance()->getConf('LOG_DIR');
            if(empty($logDir)){
                $logDir = EASYSWOOLE_ROOT.'/Log';
                Config::getInstance()->setConf('LOG_DIR',$logDir);
            }else{
                $logDir = rtrim($logDir,'/');
            }
            if(!is_dir($logDir)){
                mkdir($logDir);
            }
            defined('EASYSWOOLE_LOG_DIR') or define('EASYSWOOLE_LOG_DIR',$logDir);
    
            //设置默认文件目录值
            Config::getInstance()->setConf('MAIN_SERVER.SETTING.pid_file',$tempDir.'/pid.pid');
            Config::getInstance()->setConf('MAIN_SERVER.SETTING.log_file',$logDir.'/swoole.log');
        }
    

    $this->registerErrorHandler();

    具体的你们追下去看吧,写的真的不错,尤其是set_error_handler和register_shutdown_function

    private function registerErrorHandler()
        {
            // 显示错误
            ini_set("display_errors", "On");
            // E_STRICT出外的所有错误和警告信息。E_STRICT:启用 PHP 对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性。
            error_reporting(E_ALL | E_STRICT);
            //---------------------------------1.初始化配置Logger------------------------------
            //初始化配置Logger,install指令的时候这里获取不到logger对象,因此执行new \EasySwoole\Trace\Logger(EASYSWOOLE_LOG_DIR);
            $logger = Di::getInstance()->get(SysConst::LOGGER_HANDLER);
            if(!$logger instanceof LoggerInterface){
                $logger = new \EasySwoole\Trace\Logger(EASYSWOOLE_LOG_DIR);
            }
            // 这里的Logger和\EasySwoole\Trace\Logger不是一个
            Logger::getInstance($logger);
            //---------------------------------2.初始化追踪器------------------------------
            //初始化追踪器
            $trigger = Di::getInstance()->get(SysConst::TRIGGER_HANDLER);
            if(!$trigger instanceof TriggerInterface){
                $display = Config::getInstance()->getConf('DISPLAY_ERROR');
                $trigger = new \EasySwoole\Trace\Trigger(Logger::getInstance(),$display);
            }
            // 这里的Trigger和\EasySwoole\Trace\Trigger 不是一个
            Trigger::getInstance($trigger);
            //---------------------------------3.set_error_handler------------------------------
            //在没有配置自定义错误处理器的情况下,转化为trigger处理
            $errorHandler = Di::getInstance()->get(SysConst::ERROR_HANDLER);
            if(!is_callable($errorHandler)){
                $errorHandler = function($errorCode, $description, $file = null, $line = null){
                    $l = new Location();
                    $l->setFile($file);
                    $l->setLine($line);
                    Trigger::getInstance()->error($description,$errorCode,$l);
                };
            }
            set_error_handler($errorHandler);
            //---------------------------------3.register_shutdown_function------------------------------
            $func = Di::getInstance()->get(SysConst::SHUTDOWN_FUNCTION);
            if(!is_callable($func)){
                $func = function (){
                    $error = error_get_last();
                    if(!empty($error)){
                        $l = new Location();
                        $l->setFile($error['file']);
                        $l->setLine($error['line']);
                        Trigger::getInstance()->error($error['message'],$error['type'],$l);
                    }
                };
            }
            register_shutdown_function($func);
        }
    

    3. Install类的exec方法

        file_put_contents(EASYSWOOLE_ROOT . '/easyswoole',file_get_contents(__DIR__.'/../../../bin/easyswoole'));
    

    这里还不知道要干啥,后面用到的时候再说。

    核心代码

    public function exec(array $args): ?string
        {
            // TODO: Implement exec() method.
            // 输出logo
            echo Utility::easySwooleLog();
            // 更新easyswoole文件
            if(is_file(EASYSWOOLE_ROOT . '/easyswoole')){
                unlink(EASYSWOOLE_ROOT . '/easyswoole');
            }
            // 将easyswoole内容拷贝到__DIR__.'/../../../bin/easyswoole'中,这里我还不知道目的是什么,下面用到后再解释
            file_put_contents(EASYSWOOLE_ROOT . '/easyswoole',file_get_contents(__DIR__.'/../../../bin/easyswoole'));
            // 将下面的文件copy到/../../Resource/下
            Utility::releaseResource(__DIR__ . '/../../Resource/EasySwooleEvent.tpl', EASYSWOOLE_ROOT . '/EasySwooleEvent.php');
            Utility::releaseResource(__DIR__ . '/../../Resource/Config.tpl', EASYSWOOLE_ROOT . '/dev.php');
            Utility::releaseResource(__DIR__ . '/../../Resource/Config.tpl', EASYSWOOLE_ROOT . '/produce.php');
            echo "install success,enjoy! \n";
            return null;
        }
    

    easySwooleLog 方法

    虽然没啥逻辑,就当宣传一下easyswoole吧

    public static function easySwooleLog()
        {
            return <<<LOGO
      ______                          _____                              _
     |  ____|                        / ____|                            | |
     | |__      __ _   ___   _   _  | (___   __      __   ___     ___   | |   ___
     |  __|    / _` | / __| | | | |  \___ \  \ \ /\ / /  / _ \   / _ \  | |  / _ \
     | |____  | (_| | \__ \ | |_| |  ____) |  \ V  V /  | (_) | | (_) | | | |  __/
     |______|  \__,_| |___/  \__, | |_____/    \_/\_/    \___/   \___/  |_|  \___|
                              __/ |
                             |___/
    
    LOGO;
        }
    

    4.相关链接

    Easyswoole手册

    相关文章

      网友评论

          本文标题:Easyswoole源码分析-3-Install

          本文链接:https://www.haomeiwen.com/subject/antttctx.html