Initialize Symfony Console commands from annotated/attributed command class methods.
Currently in use in Robo (1.x+), Drush (9.x+) and Terminus (1.x+).
Symfony Console provides a set of classes that are widely used to implement command line tools. Increasingly, it is becoming popular to use annotations to describe the characteristics of the command (e.g. its arguments, options and so on) implemented by the annotated method.
Extant commandline tools that utilize this technique include:
This library provides routines to produce the Symfony\Component\Console\Command\Command from all public methods defined in the provided class.
Note If you are looking for a very fast way to write a Symfony Console-base command-line tool, you should consider using Robo, which is built on top of this library, and adds additional conveniences to get you going quickly. Use g1a/starter to quickly scaffold a new commandline tool. See Using Robo as a Framework. It is possible to use this project without Robo if desired, of course.
This is a library intended to be used in some other project. Require from your composer.json file:
"require": {
"consolidation/annotated-command": "^4"
},
The public methods of the command class define its commands, and the parameters of each method define its arguments and options. If a parameter has a corresponding "@option" annotation in the docblock, then it is an option; otherwise, it is an argument.
class MyCommandClass
{
/**
* This is the my:echo command
*
* This command will concatenate two parameters. If the --flip flag
* is provided, then the result is the concatenation of two and one.
*
* @command my:echo
* @param string $one The first parameter.
* @param string $two The other parameter.
* @param bool $flip The "flip" option
* @option flip Whether or not the second parameter should come first in the result.
* @aliases c
* @usage bet alpha --flip
* Concatenate "alpha" and "bet".
*/
public function myEcho($one, $two, $flip = false)
{
if ($flip) {
return "{$two}{$one}";
}
return "{$one}{$two}";
}
}
or via PHP 8 attributes.
#[CLI\Name(name: 'my:echo', aliases: ['c'])]
#[CLI\Help(description: 'This is the my:echo command', synopsis: "This command will concatenate two parameters. If the --flip flag\nis provided, then the result is the concatenation of two and one.",)]
#[CLI\Param(name: 'one', description: 'The first parameter')]
#[CLI\Param(name: 'two', description: 'The other parameter')]
#[CLI\Option(name: 'flip', description: 'Whether or not the second parameter should come first in the result.')]
#[CLI\Usage(name: 'bet alpha --flip', description: 'Concatenate "alpha" and "bet".')]
public function myEcho($one, $two = '', $flip = false)
{
if ($options['flip']) {
return "{$two}{$one}";
}
return "{$one}{$two}";
}
The legacy method for declaring commands is still supported. When using the legacy method, the command options, if any, are declared as the last parameter of the methods. The options will be passed in as an associative array; the default options of the last parameter should list the options recognized by the command. The rest of the parameters are arguments. Parameters with a default value are optional; those without a default value are required.
class MyCommandClass
{
/**
* This is the my:echo command
*
* This command will concatenate two parameters. If the --flip flag
* is provided, then the result is the concatenation of two and one.
*
* @command my:echo
* @param integer $one The first parameter.
* @param integer $two The other parameter.
* @param array $options An option that takes multiple values.
* @option flip Whether or not the second parameter should come first in the result.
* @aliases c
* @usage bet alpha --flip
* Concatenate "alpha" and "bet".
*/
public function myEcho($one, $two, $options = ['flip' => false])
{
if ($options['flip']) {
return "{$two}{$one}";
}
return "{$one}{$two}";
}
}
The $options array must be an associative array whose key is the name of the option, and whose value is one of:
false, which indicates that the option takes no value.--foo=bar), then the value will be a string.--foo), then the value will be true.null.--foo=0, then the value will be converted to false.null for both the no-value case (--foo) and the no-option case. When using a StringInput, use --foo=1 instead of --foo to avoid this problem.true produces the following behavior:--foo=bar), then the value will be a string.--foo), then the value will be true.true.--foo=0, then the value will be converted to false.--no-foo on the commandline, then the value of foo will be false.No other values should be used for the default value. For example, $options = ['a' => 1] is incorrect; instead, use $options = ['a' => '1'].
Default values for options may also be provided via the @default annotation. See hook alter, below.
Commandfiles may provide hooks in addition to commands. A commandfile method that contains a @hook annotation is registered as a hook instead of a command. The format of the hook annotation is:
@hook type target
The hook type determines when during the command lifecycle this hook will be called. The available hook types are described in detail below.
The hook target specifies which command or commands the hook will be attached to. There are several different ways to specify the hook target.
my:command) or the command's method name (e.g. myCommand) will attach the hook to only that command.@foo) will attach the hook to any command that is annotated with the given label.*, then the hook will be attached to all commands.There are ten types of hooks in the command processing request flow:
In addition to these, there are two more hooks available:
The "pre" and "post" varieties of these hooks, where available, give more flexibility vis-a-vis hook ordering (and for consistency). Within one type of hook, the running order is undefined and not guaranteed. Note that many validate, process and alter hooks may run, but the first status or extract hook that successfully returns a result will halt processing of further hooks of the same type.
Each hook has an interface that defines its calling conventions; however, any callable may be used when registering a hook, which is convenient if versions of PHP prior to 7.0 (with no anonymous classes) need to be supported.
The command-event hook is called via the Symfony Console command event notification callback mechanism. This happens prior to event dispatching and command / option validation. Note that Symfony does not allow the $input object to be altered in this hook; any change made here will be reset, as Symfony re-parses the object. Changes to arguments and options should be done in the initialize hook (non-interactive alterations) or the interact hook (which is naturally for interactive alterations).
The option event hook (OptionHookInterface) is called for a specific command,
| 日期 | 榜单 | 排名 | 周期新增 | 总 STAR |
|---|