phpixie/console

PHPixie控制台命令库

3.4.3 2018-02-16 00:07 UTC

This package is auto-updated.

Last update: 2024-09-13 02:05:34 UTC


README

PHPixie控制台命令组件

Author Source Code Software License

PHPixie Console 允许你在命令行中定义和运行命令。与仅仅保留一个PHP脚本文件夹相比,主要的好处是能够定义选项和参数,验证它们,生成命令用法等。

迁移现有的PHPixie项目

如果你创建了一个全新的PHPixie项目,你已经准备好了,否则你需要对项目进行一些小的修改,通过更新一些来自新项目骨架的文件

  1. https://github.com/PHPixie/Project/blob/master/console
  2. https://github.com/PHPixie/Project/blob/master/src/Project/Framework/Bundles.php
  3. "phpixie/framework-bundle": "~3.0"添加到composer.json

可选地,也可以复制控制台工厂和示例Greet命令

  1. https://github.com/PHPixie/Project/blob/master/bundles/app/src/Project/App/Console.php
  2. https://github.com/PHPixie/Project/blob/master/bundles/app/src/Project/App/Console/Greet.php
  3. 在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是数据库的名称,后面跟着我们想要导出的表的名称。这些都是命令的参数。userskip-missingf是选项。请注意,对于参数,它们指定的顺序很重要,但对于选项则不然,也可以使用单个-而不是两个来引用单字母选项。

让我们看看如何定义选项

$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