Swoft 控制台命令组件使用详解,可以作为文档或者手册使用
- 作者: 刘杰
- 来源: 技术那些事
- 阅读:13
- 发布: 2025-08-23 06:46
- 最后更新: 2025-08-23 06:48
在使用 swoft2 进行项目开发的过程中,难免会有一些需求需要用到控制台命令的帮助。比如:我想查看当前Container 中的各种类型实例分别有哪些,我新定义的类,是否已经正常初始化了。这个时候我们可以借助命令:php bin/swoft beans --type=[sig/pro/req/sess/def]
,来分别查看不同类型的 bean 的列表。详细命令说明如下:
shell
Usage:
bin/swoft app:beans [arguments ...] [options ...]
Global Options:
--debug Setting the application runtime debug level(0 - 4)
--no-color Disable color/ANSI for message output
-h, --help Display help message for application or command
-V, --version Display application version information
Options:
-e, --exclude STRING Must exclude the string on bean name
-c, --include STRING Must contains the string on bean name
--type STRING Display the bean names of the type (defaults: sig)
sig - singleton
pro - prototype
req - request
sess - session
def - definition
这个是如何实现的呢,swoft2 已经提供相关的控制台命令组件,我们只需要声明一个类,然后加上相应的命令相关的注解,在框架启动过程中,会自动解析此类,将其识别为一个命令。这时只要们通过类似上边的命令方式,就能执行我们自己定义的命令,而且相关命令提示,用法等等,都已经集成好了,非常简单便捷。
注意:以上命令,使用的是
devtool
组件中的自定义命令,如果你的没有,可以通过 composer require swoft/devtool,添加并且安装完毕后,重新执行命令即可。
下边,让我们来详细讲解下 swoft/console(控制台命令组件)的详细使用。
命令(Command)的组成
在 Swoft2 中,命令由以下几个主要部分组成,命令、操作、参数、选项。比如一个命令:php bin/swoft http:start -d
。此命令,从 http 开始为 Swoft2 的命令部分,前边 bin/swoft
相当于Swoft 的启动脚本,不在命令范围之内,但是要执行任何swoft 的命令都必须用到它。
http 是命令的主体(command),start 是命令的具体操作(action),后边的 -d
是可选参数的简写形式。一个命令主体对应的代码开发中的一个类,一个命令可以有多个操作(action),每个操作相当于类中的一个成员函数。每个操作又可以对应多个参数,多个选项,参数和选项相当于函数的输入参数。
注意,这里参数和选项是两个东西,参数在swoft的命令组件中,指的是写命令的时候,不写出参数名的值。例如:php bin/swoft http:start val1 val2 ...
,这其中的 val1 val2 ...
分别是不同的参数,参数识别是靠位置索引(第1个,第2个...)来识别的。
选项一般指的是带中划线的那些值,这些值又分为带一个中划线和两个中划线的类型。如:php bin/swoft http:start -d
或者 php bin/swoft http:start --daemon
,这两个命令其实是一样的。主命令 http 一致,操作 start 一致,-d 和 --daemon 其实是一个选项的两种不同形式。-d
这种带一个中划线的我们可以叫短选项或者快捷选项,--daemon
这种带两个中划线的,可以叫做长选项,或者完全选项。它们是一个选项的两种不同表现形式,完全是为了减少输入命令时候字数,才有了短选项。
下边继续,逐个分析命令的组成。
主命令(Command)
也可以叫命令,为了区分我们常说的命令,我这里给它取了这个名字。
@Command 类注解,可以将一个类,自动解析为命令。一个命令中应该最少含有一个操作,否则执行命令帮助时候,可能会有异常。
@Command 注解说明
- name:可选,命令的名称。一般小写,便于书写,不可以与其他命令重复,如果重复,虽然不会报错,但是可能覆盖之前的命令。不写默认会取类名(如果有后缀:Command,会先去掉),在拼接后缀 Command。
- coroutine:可选,默认为 true。命令执行时候是否使用协程,根据需要选择是否开启,某些情况不宜开启,会导致数据错乱。
- desc:可选,命令的描述。当执行
命令 --help
时候会提示,当前命令的描述信息,便于用户使用时参考 - alias:可选,命令的别名。对于比较长的命令,可以简写,减少输入,别名也要是唯一的。
- enabled:可选,命令是否启用。目前没有发现这个配置有什么用,保持默认true即可。
- example:可选,提供一个使用示例,在
命令 --help
时候会显示 Example:内容。
那如何自定一个主命令呢?
定义个主命令很简单,比如:
php
/**
* 自定义 test 命令,无任何操作
* @Command(name="test", coroutine=false, desc="测试自定义一个服务")
*/
class TestCommand {
}
假设我们有如下的命令要完成,关于搜索服务的命令,一部分是关于索引模块的命令,比如索引的创建、重建、删除等等;另一部分是关于检索模块的命令,比如测试检索内容,分页显示等等。
这里我来这样区分主命令,如果按照之前逻辑主命令应该为 search,两个模块为了区分出来应该为 index 和 search,相关的操作有 start/rebuild/delete/query 等等,那这样这个命令就分了三级,但是 swoft 中,search 对应的命令分组是不存在,没有这个概念,它很直接的将命令分为了命令和操作两个级别。所以我们得将以上划分修改一下,我将两个模块分为两个类,SearchIndex 和 SearchSearch(这不是重复,第一个代表search服务,第二个代表模块 search)。
操作(action)
不得不说,和 mvc 很相似。其实大多数要进行类似区分的时候,基本都是类似逻辑,因为比较直观。定义被标注了命令的类的一个成员函数,为一个操作,也需要对应的注解 @CommandMapping,这个注解,可以用来将命令和操作进行关联,就像http 请求的 controller 和 action 一样,绑定到路由,通过命令,进行路由就能找到对应的实际方法。
@CommandMapping 注解说明
- name:可选,命令操作名称。不写默认取成员函数名作为名称。
- alias:可选,别名。类似主命令,简化操作书写长度。
- desc:可选,描述操作的具体用处。
- usage:可选,不提供则不显示。使用说明,提供操作的具体使用方式。
这里继续完成之前搜索命令的示例代码:
php
/**
* search-search:query 示例
* Class SearchSearchCommand
*
* @Command(name="search-search", enabled=false, desc="搜索服务搜索模块相关操作")
* @example 搜索命令的示例内容,可以不提供
*/
class SearchSearchCommand {
/**
* @CommandMapping(name="query")
*
* @example 这是示例的内容,可以不提供
*
* @return void
*/
public function query()
{
output()->success('ok');
}
}
/**
* search-search:rebuild 示例
* Class SearchIndexCommand
*
* @Command(name="search-index", coroutine=false, desc="搜索服务索引相关操作")
*/
class SearchIndexCommand {
/**
* @CommandMapping(name="rebuild", usage="{fullCommand} [arguments ...] [options ...]", desc="搜索服务索引相关操作")
*
* @example 这是示例的内容,可以不提供
*
* @return void
*/
public function rebuild()
{
output()->success('ok');
}
}
参数(Arguments/Arg)
参数在命令执行的时候,实际是没有参数名的,传的直接是参数值。并且参数是通过传参的位置索引,来绑定到对应的参数名的。
如下代码所示:
通过命令行传递的参数,从第一个开始,依次会绑定到注解中的 @CommandArgument 注解。两个顺序是一致的。即第一个参数,绑定到 url,第二个参数绑定到 test
php
/**
* @CommandMapping(name="push", alias="push", desc="Push url to search engine.")
*
* @CommandOption(name="engine", type="array", short="eg", default={"baidu"}, mode=Command::OPT_IS_ARRAY)
*
* @CommandArgument(name="url", type="string", required=true, mode=Command::ARG_REQUIRED)
* @CommandArgument(name="test", type="string", required=true, mode=Command::ARG_REQUIRED)
* @example 提供一个示例,在帮助中显示
*
* @param Input $input
* @param Output $output
* @return void
* @throws CommandFlagException
*/
// 假设命令为: php sitemap:push [第一个参数] [第二个参数] -eg=baidu
// 上边第一个参数就相当于 url 的值,第二个参数相当于 test 的值。
// 参数不同于 opt(可选)参数,不需要参数名=参数值这种形式。
@CommandArgument 注解说明
- name:必填,参数名。不写在命令中,但是代码中获取对应的参数后,参数数组的键名会以此命名。不过获取参数的顺序还是要和命令中参数顺序一致。
- desc:可选,参数描述信息。--help 时候显示的信息。
- type:可选,默认值为 value。表示获取参数信息时候,获取到的是参数的值。
- required:可选,默认值为 false。表示书写命令时候,是否必须有此参数。
- optional:可选,默认为 true。表示此参数是否可以选,可以配合 default,默认值来使用。
- array:可选,默认为false。表示此值是否可以传递多个,比如:
- mode:可选,默认为 0。值的二进制表示,001 表示参数必须,010 表示参数可选,100表示参数是数组。这个功能,目前官方代码没有实现完全,array是不支持的。关于 array 的选项尽量不要设置。
注意,参数只能给成员函数设置注解,不能给类设置注解。
根据以上可以完善下之前search 的示例:
php
/**
* Class SearchIndexCommand
*
* @Command(name="search-index", coroutine=false, desc="搜索服务索引相关操作")
*/
class SearchIndexCommand {
/**
* @CommandMapping(name="related", desc="获取相关搜索词")
* @CommandArgument(name="keyword", type="string", desc="搜索关键词")
* @example search-search related swoft2 -l 10 ; 获取 swoft2 相关搜索词
*
* @param Input $input
* @param Output $output
* @return void
* @throws XSException|CommandFlagException
*/
public function related(Input $input, Output $output)
{
}
}
/**
* Class SearchSearchCommand
*
* @Command(name="search-search", coroutine=false, desc="搜索服务搜索模块相关操作")
* @CommandOption(name="dbName", short="db", default="db", desc="索引数据库名称")
* @example search-search query swoft2
*/
class SearchSearchCommand {
/**
* @CommandMapping(name="query")
*
* @CommandArgument(name="keyword", type="string", desc="搜索关键词")
*
* @param Input $input
* @param Output $output
* @return void
* @throws CommandFlagException
* @throws XSException
*/
public function query(Input $input, Output $output): void {
}
}
选项(Options/Opt)
选项注解,既可以放到成员函数上,又可以放到类上。放到类上,表示是全局选项,此命令内的所有操作,都共享这个选项,都可以通过此选项获取选项值。而放到成员方法上,则只有此方法对应的操作会有此选项。其他操作不会有此选项。
@CommandOption 注解说明
- name:必须,选项全称。eg:
--test val
这其中的 test 就是参数名。 - short:可选,选项简写。配置
short="t"
之后,以上可以简写成 -t val。 - type:可选,选项类型。默认是value。可以设置为:string/int/integer 等等。
- default:可选,默认选项值。设置为 required=true 时候,没有传此参数,会获得此值。
- desc:可选,选项描述信息。
- required:可选,默认为false。此值设置为true后,命令行中必须由此选项,否则会报异常。
php
// 选项的书写方式支持一下方式
-e
-e <value>
-e=<value>
--long-opt
--long-opt <value>
--long-opt=<value>
根据以上,在完善下之前的搜索相关的示例:
php
/**
* Class SearchIndexCommand
*
* @Command(name="search-index", coroutine=true, desc="搜索服务索引相关操作")
* @CommandOption(name="dbName", short="db", default="db", desc="索引数据库名称")
*/
class SearchIndexCommand {
/**
* @CommandMapping(name="rebuild", usage="{fullCommand} [arguments ...] [options ...]", desc="搜索服务索引相关操作")
* @CommandOption(name="limit", short="l", type="int", default=20, desc="每次循环从数据源处理的数据条数")
* @CommandOption(name="buf", short="b", type="bool", default=true, desc="是否开启索引构建缓冲区")
*
* @param Input $input
* @param Output $output
* @return void
* @throws CommandFlagException
*/
public function index(Input $input, Output $output): void {}
/**
* 清空索引数据(慎用)
*
* @CommandMapping(name="clean", desc="清空当前索引数据库")
*
* @param Input $input
* @param Output $output
* @return void
*/
public function clean(Input $input, Output $output) {}
}
/**
* Class SearchSearchCommand
*
* @Command(name="search-search", coroutine=false, desc="搜索服务搜索模块相关操作")
* @CommandOption(name="dbName", short="db", default="db", desc="索引数据库名称")
* @example search-search query swoft2
*/
class SearchSearchCommand {
/**
* @CommandMapping(name="query")
*
* @CommandArgument(name="keyword", type="string", desc="搜索关键词")
* @CommandOption(name="limit", short="l", type="int", default=10, desc="每页数量")
* @CommandOption(name="offset", short="o", type="int", default=0, desc="偏移量")
* @CommandOption(name="addDb", short="a", type="string", default="", desc="添加要检索的索引数据库名称")
* @CommandOption(name="fuzzy", short="f", type="bool", default=false, desc="是否开启模糊搜索")
*
* @param Input $input
* @param Output $output
* @return void
* @throws CommandFlagException
* @throws XSException
*/
public function query(Input $input, Output $output): void {}
/**
* @CommandMapping(name="related", desc="获取相关搜索词")
* @CommandArgument(name="keyword", type="string", desc="搜索关键词")
* @CommandOption(name="limit", short="l", type="int", default=10, desc="相关搜索词数量,最大20条")
* @example search-search related swoft2 -l 10 ; 获取 swoft2 相关搜索词
*
* @param Input $input
* @param Output $output
* @return void
* @throws XSException|CommandFlagException
*/
public function related(Input $input, Output $output) {}
}
以上示例,基本涉及到了 Swoft 控制台命令组件的各个细节,如果还有不明白的可以到网站留言,我会根据建议进一步完善。