phpixie / console
PHPixie控制台命令库
Requires
- phpixie/cli: ~3.1
- phpixie/slice: ~3.0
Requires (Dev)
- phpixie/test: ~3.0
README
PHPixie控制台命令组件
PHPixie Console 允许你在命令行中定义和运行命令。与仅仅保留一个PHP脚本文件夹相比,主要的好处是能够定义选项和参数,验证它们,生成命令用法等。
迁移现有的PHPixie项目
如果你创建了一个全新的PHPixie项目,你已经准备好了,否则你需要对项目进行一些小的修改,通过更新一些来自新项目骨架的文件
- https://github.com/PHPixie/Project/blob/master/console
- https://github.com/PHPixie/Project/blob/master/src/Project/Framework/Bundles.php
- 将
"phpixie/framework-bundle": "~3.0"
添加到composer.json
可选地,也可以复制控制台工厂和示例Greet命令
- https://github.com/PHPixie/Project/blob/master/bundles/app/src/Project/App/Console.php
- https://github.com/PHPixie/Project/blob/master/bundles/app/src/Project/App/Console/Greet.php
- 在Builder中注册控制台类,如下:https://github.com/PHPixie/Project/blob/master/bundles/app/src/Project/App/Builder.php
运行命令
现在尝试运行控制台脚本
cd your_project_directory/
./console
这将列出可用的命令及其描述,例如:
Available commands:
app:greet Greet the user
framework:installWebAssets Symlink or copy bundle web files to the projects web folder
framework:generateBundle Generate a new bundle
help Print command list and usage
您可以使用help
命令获取有关命令的扩展信息
./console help framework:installWebAssets
framework:installWebAssets [ --copy ]
Symlink or copy bundle web files to the projects web folder
Options:
copy Whether to copy web directories instead of symlinking them
默认命令
framework:installWebAssets 其目的是从捆绑目录创建到/web/bundles文件夹的符号链接,例如 /web/bundles/app -> /bundles/app/web。背后的想法是我们可以有可以通过composer安装和更新的捆绑包,它们提供自己的网络资产。--copy
标志将复制目录而不是创建符号链接。这对于您想随后将文件部署到CDN网络很有用。
framework:generateBundle 此命令生成并注册项目中的新捆绑包。
添加自己的命令
骨架项目中提供了一个名为app:greet
的示例命令。它们以与HTTP处理器相同的方式添加,使用\Project\App\Console
类。要添加新命令,您必须将其名称添加到由commandNames
方法返回的数组中,并创建一个build<command_name>Command
方法。
您可以为命令配置以添加描述并定义选项和参数。让我们看看默认的Greet
命令
namespace Project\App\Console; class Greet extends \PHPixie\Console\Command\Implementation { public function __construct($config) { // Specify command description $config->description('Greet the user'); //Define a 'message' argument $config->argument('message') ->description("Message to display"); parent::__construct($config); } /** * Gets called when the command is executed. * $argumentData and $optionData work in the same * way as HTTP $request->query() and $request->data() */ public function run($argumentData, $optionData) { $message = $argumentData->get('message', "Have fun coding!"); $this->writeLine($message); } }
参数和选项
假设我们想定义一个命令,该命令从数据库中导出一些表,一个典型的调用可能看起来像这样:
sqldump --user=root --skip-missing -f myDatabase users items
在这里,myDatabase
是数据库的名称,后面跟着我们想要导出的表的名称。这些都是命令的参数。user
、skip-missing
和f
是选项。请注意,对于参数,它们指定的顺序很重要,但对于选项则不然,也可以使用单个-
而不是两个来引用单字母选项。
让我们看看如何定义选项
$config->option('user') //Mark option as required ->required() //Describe what the option does. //this is displayed by the 'help' command ->description("User to connect to the database with"); $config->option('skip-missing') ->description("Don't throw an error if the tables are missing") //mark option as flag, //flag options don't accept a value, //but are set to 'true' if they are present. ->flag(); $config->option('f') ->flag() ->description("Force database dump");
在定义参数时,您必须记住,它们应该按照它们应该指定的顺序定义。在我们的例子中,这意味着我们必须在定义tables
参数之前定义database
参数
$config->argument('database') ->required() ->description("Which database to dump the tables from"); $config->argument('tables') ->description("Tables to dump") // Can accept more than one value. // There can be only one argument marked with `arrayOf` // and it has to be the last one. ->arrayOf();
如果我们现在运行help
命令,我们会看到以下内容:
./console help app:sqldump
app:sqldump --user=VALUE [ -f ] [ --skip-missing ] DATABASE [ TABLES... ]
Options:
user User to connect to the database with
f Force database dump
skip-missing Don't throw an error if the tables are missing
Arguments:
DATABASE Which database to dump the tables from
TABLES Tables to dump
当执行命令时,命令的 run
方法接收传递的选项和参数,可以像处理 HTTP 请求一样访问它们。
public function run($argumentData, $optionData) { $database = $argumentData->get('database'); // specifying default value $user = $optionData->get('user', 'phpixie'); }
输入和输出
从命令中返回输出的最简单方法是通过 return
一个字符串。但是一些命令需要一段时间才能处理,你可能希望向用户提供中间状态。你可以使用一些额外的功能。
public function run($argumentData, $optionData) { // Write text without line break $this->write("Hello "); // Write text with new line $this->writeLine("World"); // Read a line of user input $str = $this->readLine(); // Throwing a CommandException will output the error message // and ensure that the command exits with a non-zero exit code throw new \PHPixie\Console\Exception\CommandException("Something bad happened"); }
要进一步控制输入和输出,你可以使用 CLI 上下文,实际上上述方法只是 CLI 上下文调用的快捷方式。
public function run($argumentData, $optionData) { $context = $this->cliContext(); $inputStream = $cliContext->inputStream(); $outputStream = $cliContext->outputStream(); $errorStream = $cliContext->errorStream(); $outputStream->write("Hello"); $errorStream->writeLine("Something bad happened"); $context->setExitCode(1); // set the exit code }
退出码很重要,如果你想要在外部检查命令是否成功执行,例如在 Bash 中,如果你做类似以下的事情:
if ./console app:somecommand ; then
echo "Command succeeded"
else
echo "Command failed"
fi