- 
                Notifications
    You must be signed in to change notification settings 
- Fork 48
v4 create group
        Inhere edited this page May 28, 2022 
        ·
        6 revisions
      
    通过 Controller 形式可以简单快速的组织一组相关命令。在v4版本,命令组同样进行了增强,可以支持嵌入独立命令当做子命令
先看一个代码示例片段,来自我的工具应用项目 inhere/kite
<?php declare(strict_types=1);
namespace Inhere\Kite\Console\Controller;
use Inhere\Console\Controller;
use Inhere\Console\Exception\PromptException;
use Inhere\Console\IO\Input;
use Inhere\Console\IO\Output;
use Inhere\Kite\Console\Component\Clipboard;
use Inhere\Kite\Common\Cmd;
use Inhere\Kite\Common\CmdRunner;
use Inhere\Kite\Helper\AppHelper;
use Inhere\Kite\Helper\GitUtil;
use PhpGit\Changelog\Filter\KeywordsFilter;
use PhpGit\Changelog\Formatter\GithubReleaseFormatter;
use PhpGit\Changelog\Formatter\SimpleFormatter;
use PhpGit\Changelog\GitChangeLog;
use PhpGit\Git;
use PhpGit\Info\TagsInfo;
use PhpGit\Repo;
use Throwable;
use Toolkit\PFlag\FlagsParser;
use Toolkit\Stdlib\Obj\ConfigObject;
use Toolkit\Stdlib\Str;
/**
 * Class GitController
 */
class GitController extends Controller
{
    protected static $name = 'git';
    protected static $description = 'Provide useful tool commands for quick use git';
    /**
     * @var ConfigObject
     */
    private $settings;
    public static function aliases(): array
    {
        return ['g'];
    }
    protected static function commandAliases(): array
    {
        return [
            'changelog'    => ['chlog', 'clog', 'cl'],
            'log'          => ['l', 'lg'],
        ];
    }
    /**
     * @return string[]
     */
    protected function options(): array
    {
        return [
            '--dry-run' => 'bool;Dry-run the workflow, dont real execute',
            '-y, --yes' => 'Direct execution without confirmation',
            // '-i, --interactive' => 'Run in an interactive environment[TODO]',
        ];
    }
    protected function beforeRun(): void
    {
        if ($this->app && !$this->settings) {
            $this->settings = ConfigObject::new($this->app->getArrayParam('git'));
        }
    }
    
    /**
     * display recently git commits information by `git log`
     *
     * @arguments
     *  maxCommit       int;Max display how many commits;;15
     *
     * @options
     *  --ac, --abbrev-commit     bool;Only display the abbrev commit ID
     *  --exclude                 Exclude contains given sub-string. multi by comma split.
     *  --file                    Export changelog message to file
     *  --format                  The git log option `--pretty` value.
     *                            can be one of oneline, short, medium, full, fuller, reference, email, raw, format:<string> and tformat:<string>.
     *  --mc, --max-commit        int;Max display how many commits
     *  --nc, --no-color          bool;Dont use color render git output
     *  --nm, --no-merges         bool;No contains merge request logs
     *
     * @param FlagsParser $fs
     * @param Output $output
     */
    public function logCommand(FlagsParser $fs, Output $output): void
    {
        $b = Git::new()->newCmd('log');
        $noColor = $fs->getOpt('no-color');
        $exclude = $fs->getOpt('exclude');
        $noMerges  = $fs->getOpt('no-merges');
        $abbrevID  = $fs->getOpt('abbrev-commit');
        $maxCommit = $fs->getOpt('max-commit', $fs->getArg('maxCommit'));
        // git log --color --graph --pretty=format:'%Cred%h%Creset:%C(ul yellow)%d%Creset %s (%Cgreen%cr%Creset, %C(bold blue)%an%Creset)' --abbrev-commit -10
        $b->add('--graph');
        $b->addIf('--color', !$noColor);
        $b->add('--pretty=format:"%Cred%h%Creset:%C(ul yellow)%d%Creset %s (%Cgreen%cr%Creset, %C(bold blue)%an%Creset)"');
        $b->addIf("--exclude=$exclude", $exclude);
        $b->addIf('--abbrev-commit', $abbrevID);
        $b->addIf('--no-merges', $noMerges);
        $b->add('-' . abs($maxCommit));
        $b->runAndPrint();
        $output->success('Complete');
    }
}TIP: 创建好命令后需要注册到 Application 才能运行, 请看 注册命令 章节
- 必须继承基础类 Inhere\Console\Controller
- 
$name命令组名称,必须且不能为空
- 
$desc命令组描述说明
- 所有公开的且符合 {name}Command格式的方法都是命令组的子命令
命令渲染效果 kite git -h:
 
可以观察到上面示例的 logCommand 方法注释是有一定格式的。
跟独立命令一样,命令组里的子命令也可以通过方法注释快速绑定命令选项和参数,运行时console会自动解析并绑定到当前命令
- 
@arguments后面的即是命令参数
- 
@options后面的即是命令选项- 注意选项名和后面的设置描述需间隔一定距离
- 规则以分号 ;分割每个部分 (完整规则:type;desc;required;default;shorts)
- 默认是 string 类型,可以忽略
 
选项参数解析使用的 php-toolkit/pflag 更多说明可以点击查看
我们可以使用 -h 选项查看添加选项后效果
执行 ./bin/myapp.php git log -h:

运行 kite git log 即会调用 GitController::logCommand():
kite git log
# 添加选项和参数
kite git log 2
kite git log --abbrev-commit 5注意运行命令应当遵循通用的Linux命令调用格式:
ENTRY CMD --OPTIONS ARGUMENTS
运行效果:

跟独立命令类似,通过 aliases() 方法可以设置当前命令组的别名
    /**
     * @return string[]
     */
    public static function aliases(): array
    {
        return ['g'];
    }设置别名后,通过别名 kite g 也可以访问执行命令组。
命令组里还可以通过 commandAliases 给内部的子命令添加别名,方便使用。
如下所示,添加别名后 kite git l 就相当于执行 kite git log
    protected static function commandAliases(): array
    {
        return [
            'changelog'    => ['chlog', 'clog', 'cl'],
            'log'          => ['l', 'lg'],
        ];
    }在命令组里,我们还可以直接给命令组绑定选项设置。
    /**
     * @return string[]
     */
    protected function getOptions(): array
    {
        return [
            '--try,--dry-run' => 'bool;Dry-run the workflow, dont real execute',
            '-y, --yes'       => 'bool;Direct execution without confirmation',
            '-w, --workdir'   => 'The command work dir, default is current dir.',
        ];
    }使用时注意,命令组的选项应当跟随命令组。例如
kite git --workdir another/dir log 2默认是查看当前目录的git log, 加上命令组选项
--workdir another/dir则会在another/dir执行git log命令
- 
protected function annotationVars(): array继承此方法可以添加自定义的帮助信息变量,可以在命令注释里使用
- 
protected function beforeExecute(): bool将会在每个子命令执行前调用
- 更多请查看命令的父类 Inhere\Console\Handler\AbstractHandler拥有的方法
我的其他PHP项目
- inhere/kite 方便本地开发和使用的个人CLI工具应用
- php-toolkit/pflag PHP编写的,通用的命令行标志(选项和参数)解析库
- phppkg/easytpl 使用简单且快速的 PHP 模板引擎
- inhere/php-validate 一个简洁小巧且功能完善的php验证库
- inhere/sroute 轻量且快速的HTTP请求路由库