EasySwoole命令行Command分析
和阅读其他FPM框架源码一样需要从入口文件跟入. 在EasySwoole中启动方式是 php easyswoole start
easyswoole其实就是php文件,只是省略了后缀
在开头定义了几个常量
// 判断是否在PHAR环境下运行, 当前返回False
defined('IN_PHAR') or define('IN_PHAR', boolval(\Phar::running(false)));
// 获取运行目录 /www/wwwroot/es_study
defined('RUNNING_ROOT') or define('RUNNING_ROOT', realpath(getcwd()));
// 获取easyswoole目录 /www/wwwroot/es_study
defined('EASYSWOOLE_ROOT') or define('EASYSWOOLE_ROOT', IN_PHAR ? \Phar::running() : realpath(getcwd()));
然后引入Composer自动加载
// 引用 Composer 自动加载
$file = EASYSWOOLE_ROOT.'/vendor/autoload.php';
if (file_exists($file)) {
require $file;
}else{
die("include composer autoload.php fail\n");
}
这里还有引入了一个bootstrap.php
默认不存在需要自己新建,它允许用户在框架初始化之前执行自定义事件
if(file_exists(EASYSWOOLE_ROOT.'/bootstrap.php')){
require_once EASYSWOOLE_ROOT.'/bootstrap.php';
}
最后接收Cli参数, 并弹出第一位. 只需要获取到 第二位之后的即可.
# $argv的内容
array(2) {
[0]=>
string(32) "/www/wwwroot/es_study/easyswoole"
[1]=>
string(7) "start"
}
$args = $argv;
//trim first command
array_shift($args);
当我们以 php easyswoole start
启动框架的时候,会将 cli参数 传入 CommandRunner::getInstance()->run($args);
类调用使用了 getInstance
方法,是一个单例模式. CommandRunner
也就是我们今天的主题了,继续跟入.
该类的文件在 vendor/easyswoole/easyswoole/src/Command
下. 顺便看下其他文件.可以知道DefaultCommand
里放着的是命令参数.还实现了一个CommandContainer
容器.
Utility
类主要实现了一些辅助功能.
`easySwooleLog` 在终端打印出easySwoole的LOGO
`displayItem` 终端显示一些文本
`releaseResource` 复制文件
`opCacheClear` 清除opcache缓存和Apuc缓存
继续看我们的CommandRunner
类.
class CommandRunner
{
// 引用单例
use Singleton;
}
这里通过一个trait实现了一个单例的方法.
该类的构造方法注册了框架自带的命令
function __construct()
{
// 注册命令
CommandContainer::getInstance()->set(new Help());
CommandContainer::getInstance()->set(new Install());
CommandContainer::getInstance()->set(new Start());
CommandContainer::getInstance()->set(new Stop());
CommandContainer::getInstance()->set(new Reload());
CommandContainer::getInstance()->set(new PhpUnit());
CommandContainer::getInstance()->set(new Restart());
CommandContainer::getInstance()->set(new Config());
}
该类还剩一个run方法
// CommandRunner::getInstance()->run($args);
function run(array $args):?string
{
// 弹出元素 `start`
$command = array_shift($args);
if(empty($command)){ // 如果为空就显示帮助信息
$command = 'help';
}else if($command != 'install'){ // 判断是否为安装模式,在composer下载完成后需要install才能正常使用
//预先加载配置
if(in_array('produce',$args)){
Core::getInstance()->setIsDev(false); // 如果命令行参数中带有produce则是生产环境
}
Core::getInstance()->initialize(); // 初始化操作
}
if(!CommandContainer::getInstance()->get($command)){ // 判断是否有此命令,没有则为help帮助信息
$command = 'help';
}
return CommandContainer::getInstance()->hook($command,$args); // 通过容器调用相应的类进行操作
}
}
Core类这里是框架核心类. 我们之后在做具体介绍. 现在接着分析CommandContainer
类.
container
属性里面存着命令参数和对应类的实例化. CommandRunner
类的构造方法里set出具体命令实例化对象.
然后通过CommandContainer::getInstance()->hook($command,$args)
hook方法调用具体的类.
调用的所有命令类.需要实现CommandInterface
接口.
interface CommandInterface
{
public function commandName():string; // 命令名
public function exec(array $args):?string ; // 操作
public function help(array $args):?string ; // 帮助信息
}
那我们如何实现一个自定义的命令呢?
1.编一个类实现CommandInterface
里的所有方法
2.在根目录的bootstrap里set出你新建的类
\EasySwoole\EasySwoole\Command\CommandContainer::getInstance()->set(new \App\Command\Test());
大功告成,你也可以使用自己的方法了. 例如php easyswoole test
框架自带的命令也不一一分析了.后面我们以start
命令做深入讲解.毕竟这是我们的启动命令.
No Comments