包 | system.console |
---|---|
继承 | abstract class CConsoleCommand » CComponent |
子类 | CHelpCommand |
源自 | 1.0 |
版本 | $Id: CConsoleCommand.php 3548 2012-01-24 11:42:59Z mDOMba $ |
源码 |
CConsoleCommand代表一个可执行的控制台命令。
它的工作原理跟CController一样,通过解析命令行选项和根据适当的选项值将 请求调度到一个指定的动作。
用户通过以下命令格式来调用控制台命令:
子类主要实现各种动作方法,这个动作方法名必 须以“action”作为前缀。 传递给动作方法的参数被认为是指定动作的选项。 通过指定defaultAction来实现当用户没有在命令里面明确调用某个命令时 默认会调用哪个动作。
选项通过参数名称绑定到动作参数。例如,下面 的动作方法会允许我们运行命令
它的工作原理跟CController一样,通过解析命令行选项和根据适当的选项值将 请求调度到一个指定的动作。
用户通过以下命令格式来调用控制台命令:
yiic CommandName ActionName --Option1=Value1 --Option2=Value2 ...
子类主要实现各种动作方法,这个动作方法名必 须以“action”作为前缀。 传递给动作方法的参数被认为是指定动作的选项。 通过指定defaultAction来实现当用户没有在命令里面明确调用某个命令时 默认会调用哪个动作。
选项通过参数名称绑定到动作参数。例如,下面 的动作方法会允许我们运行命令
yiic sitemap --type=News
:
class SitemapCommand { public function actionIndex($type) { .... } }
公共属性
属性 | 类型 | 描述 | 定义在 |
---|---|---|---|
commandRunner | CConsoleCommandRunner | 命令执行对象的实例 | CConsoleCommand |
defaultAction | string | 默认动作的名字。 | CConsoleCommand |
help | string | 提供命令描述。 | CConsoleCommand |
name | string | 命令名字。 | CConsoleCommand |
optionHelp | array | 提供命令帮助信息选项。 | CConsoleCommand |
公共方法
方法 | 描述 | 定义在 |
---|---|---|
__call() | 如果类中没有调的方法名,则调用这个方法。 | CComponent |
__construct() | 构造方法。 | CConsoleCommand |
__get() | 返回一个属性值、一个事件处理程序列表或一个行为名称。 | CComponent |
__isset() | 检查一个属性是否为null。 | CComponent |
__set() | 设置一个组件的属性值。 | CComponent |
__unset() | 设置一个组件的属性为null。 | CComponent |
asa() | 返回这个名字的行为对象。 | CComponent |
attachBehavior() | 附加一个行为到组件。 | CComponent |
attachBehaviors() | 附加一个行为列表到组件。 | CComponent |
attachEventHandler() | 为事件附加一个事件处理程序。 | CComponent |
buildFileList() | 建立目录的文件列表。 | CConsoleCommand |
canGetProperty() | 确定属性是否可读。 | CComponent |
canSetProperty() | 确定属性是否可写。 | CComponent |
confirm() | 通过输入y或者n来询问用户确定。 | CConsoleCommand |
copyFiles() | 将文件从一个地方复制到另一个地方。 | CConsoleCommand |
detachBehavior() | 从组件中分离一个行为。 | CComponent |
detachBehaviors() | 从组件中分离所有行为。 | CComponent |
detachEventHandler() | 分离一个存在的事件处理程序。 | CComponent |
disableBehavior() | 禁用一个附加行为。 | CComponent |
disableBehaviors() | 禁用组件附加的所有行为。 | CComponent |
enableBehavior() | 启用一个附加行为。 | CComponent |
enableBehaviors() | 启用组件附加的所有行为。 | CComponent |
ensureDirectory() | 所有的父目录中如果哪个不存在,则创建它。 | CConsoleCommand |
evaLuateExpression() | 计算一个PHP表达式,或根据组件上下文执行回调。 | CComponent |
getCommandRunner() | 返回命令执行对象的实例 | CConsoleCommand |
getEventHandlers() | 返回一个事件的附加处理程序列表。 | CComponent |
getHelp() | 提供命令描述。 | CConsoleCommand |
getName() | 返回命令名字。 | CConsoleCommand |
getOptionHelp() | 提供命令帮助信息选项。 | CConsoleCommand |
hasEvent() | 确定一个事件是否定义。 | CComponent |
hasEventHandler() | 检查事件是否有附加的处理程序。 | CComponent |
hasProperty() | 确定属性是否被定义。 | CComponent |
init() | 初始化命令对象。 | CConsoleCommand |
pluralize() | 将单词转换为它的复数形式。 | CConsoleCommand |
prompt() | 如果readline这个PHP扩展可用,则通过它读取输入的内容,否则通过fgets()来读取。 | CConsoleCommand |
raiseEvent() | 发起一个事件。 | CComponent |
renderFile() | 渲染一个视图文件。 | CConsoleCommand |
run() | 执行命令。 | CConsoleCommand |
usageError() | 显示一个运行错误。 | CConsoleCommand |
受保护方法
方法 | 描述 | 定义在 |
---|---|---|
afterAction() | 这个方法会在一个动作执行完成后发起。 | CConsoleCommand |
beforeaction() | 这个方法会在一个动作执行前发起。 | CConsoleCommand |
resolveRequest() | 解析命令行参数然后决定要运行哪个动作。 | CConsoleCommand |
属性详细
commandRunner
属性
只读
public CConsoleCommandRunner getCommandRunner()
命令执行对象的实例
defaultAction
属性
(可用自 v1.1.5)
public string $defaultAction;
默认动作的名字。
help
属性
只读
public string getHelp()
提供命令描述。 这个方法可被重写,然后返回实际的命令描述。
name
属性
只读
public string getName()
命令名字。
optionHelp
属性
只读 (可用自 v1.1.5)
public array getOptionHelp()
提供命令帮助信息选项。 默认实现的是返回所有可用的动作, 同时返回相关的选项信息。
方法详细
__construct()
方法
public void __construct(string $name, CConsoleCommandRunner $runner)
| ||
$name | string | 命令名字 |
$runner | CConsoleCommandRunner | 命令执行对象 |
public function __construct($name,$runner)
{
$this->_name=$name;
$this->_runner=$runner;
}
构造方法。
afterAction()
方法
protected void afterAction(string $action, array $params)
| ||
$action | string | 动作名字 |
$params | array | 传递给动作方法的参数。 |
protected function afterAction($action,$params)
{
}
这个方法会在一个动作执行完成后发起。 你可以重写这个方法在动作之后来做一些最后处理。
beforeAction()
方法
protected boolean beforeAction(string $action, array $params)
| ||
$action | string | 动作名字 |
$params | array | 传递给动作方法的参数。 |
{return} | boolean | 返回值说明这个动作是否会执行。 |
protected function beforeAction($action,$params)
{
return true;
}
这个方法会在一个动作执行前发起。 你可以重写这个方法,使它在动作执行前来做一些处理。
buildFileList()
方法
public array buildFileList(string $sourceDir, string $targetDir, string $baseDir='')
| ||
$sourceDir | string | 源目录 |
$targetDir | string | 目标目录 |
$baseDir | string | 根目录 |
{return} | array | 文件列表(参考copyFiles) |
public function buildFileList($sourceDir, $targetDir, $baseDir='')
{
$list=array();
$handle=opendir($sourceDir);
while(($file=readdir($handle))!==false)
{
if($file==='.' || $file==='..' || $file==='.svn' ||$file==='.yii')
continue;
$sourcePath=$sourceDir.DIRECTORY_SEPARATOR.$file;
$targetPath=$targetDir.DIRECTORY_SEPARATOR.$file;
$name=$baseDir===''?$file : $baseDir.'/'.$file;
$list[$name]=array('source'=>$sourcePath, 'target'=>$targetPath);
if(is_dir($sourcePath))
$list=array_merge($list,$this->buildFileList($sourcePath,$targetPath,$name));
}
closedir($handle);
return $list;
}
建立目录的文件列表。 这个方法遍历指定的目录, 然后建立文件列表和它们包含的子目录。 这个方法的结果可以传递给copyFiles。
confirm()
方法
(可用自 v1.1.9)
public bool confirm(string $message)
| ||
$message | string | 在用户输入之前输出的内容 |
{return} | bool | 返回值说明用户是否确定。 |
public function confirm($message)
{
echo $message.' [yes|no] ';
return !strncasecmp(trim(fgets(STDIN)),'y',1);
}
通过输入y或者n来询问用户确定。
copyFiles()
方法
public void copyFiles(array $fileList)
| ||
$fileList | array | 要复制的文件列表(名字=》说明)。
在复制过程中,数组键名是显示出来的名字,数组键值是复制的
文件的规格。每一个数组值一定是以下的数组结构:
|
public function copyFiles($fileList)
{
$overwriteAll=false;
foreach($fileList as $name=>$file)
{
$source=strtr($file['source'],'/\\',DIRECTORY_SEPARATOR);
$target=strtr($file['target'],'/\\',DIRECTORY_SEPARATOR);
$callback=isset($file['callback']) ? $file['callback'] : null;
$params=isset($file['params']) ? $file['params'] : null;
if(is_dir($source))
{
$this->ensureDirectory($target);
continue;
}
if($callback!==null)
$content=call_user_func($callback,$source,$params);
else
$content=file_get_contents($source);
if(is_file($target))
{
if($content===file_get_contents($target))
{
echo " unchanged $name\n";
continue;
}
if($overwriteAll)
echo " overwrite $name\n";
else
{
echo " exist $name\n";
echo " ...overwrite? [Yes|No|All|Quit] ";
$answer=trim(fgets(STDIN));
if(!strncasecmp($answer,'q',1))
return;
else if(!strncasecmp($answer,'y',1))
echo " overwrite $name\n";
else if(!strncasecmp($answer,'a',1))
{
echo " overwrite $name\n";
$overwriteAll=true;
}
else
{
echo " skip $name\n";
continue;
}
}
}
else
{
$this->ensureDirectory(dirname($target));
echo " generate $name\n";
}
file_put_contents($target,$content);
}
}
将文件从一个地方复制到另一个地方。
参见
- buildFileList
ensureDirectory()
方法
public void ensureDirectory(string $directory)
| ||
$directory | string | 要检查的目录 |
public function ensureDirectory($directory)
{
if(!is_dir($directory))
{
$this->ensureDirectory(dirname($directory));
echo " mkdir ".strtr($directory,'\\','/')."\n";
mkdir($directory);
}
}
所有的父目录中如果哪个不存在,则创建它。
getCommandRunner()
方法
public CConsoleCommandRunner getCommandRunner()
| ||
{return} | CConsoleCommandRunner | 命令执行对象的实例 |
public function getCommandRunner()
{
return $this->_runner;
}
getHelp()
方法
public string getHelp()
| ||
{return} | string | 命令描述。默认是‘Usage: php entry-script.php command-name’。 |
public function getHelp()
{
$help='Usage: '.$this->getCommandRunner()->getScriptName().' '.$this->getName();
$options=$this->getOptionHelp();
if(empty($options))
return $help;
if(count($options)===1)
return $help.' '.$options[0];
$help.=" <action>\nActions:\n";
foreach($options as $option)
$help.=' '.$option."\n";
return $help;
}
提供命令描述。 这个方法可被重写,然后返回实际的命令描述。
getName()
方法
public string getName()
| ||
{return} | string | 命令名字。 |
public function getName()
{
return $this->_name;
}
getOptionHelp()
方法
(可用自 v1.1.5)
public array getOptionHelp()
| ||
{return} | array | 命令帮助信息选项。每一个数组元素描述了 一个独立的动作帮助信息。 |
public function getOptionHelp()
{
$options=array();
$class=new ReflectionClass(get_class($this));
foreach($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method)
{
$name=$method->getName();
if(!strncasecmp($name,'action',6) && strlen($name)>6)
{
$name=substr($name,6);
$name[0]=strtolower($name[0]);
$help=$name;
foreach($method->getParameters() as $param)
{
$optional=$param->isDefaultValueAvailable();
$defaultValue=$optional ? $param->getDefaultValue() : null;
$name=$param->getName();
if($optional)
$help.=" [--$name=$defaultValue]";
else
$help.=" --$name=value";
}
$options[]=$help;
}
}
return $options;
}
提供命令帮助信息选项。 默认实现的是返回所有可用的动作, 同时返回相关的选项信息。
init()
方法
(可用自 v1.1.6)
public void init()
|
public function init()
{
}
初始化命令对象。 这个方法是在命令对象被创建然后根据配置初始化之后执行的。 你可以重写这个方法,使它在命令执行之前来做更多的处理。
pluralize()
方法
public string pluralize(string $name)
| ||
$name | string | 要变成复数的单词 |
{return} | string | 已经变成复数的单词 |
public function pluralize($name)
{
$rules=array(
'/move$/i' => 'moves',
'/foot$/i' => 'feet',
'/child$/i' => 'children',
'/human$/i' => 'humans',
'/man$/i' => 'men',
'/tooth$/i' => 'teeth',
'/person$/i' => 'people',
'/([m|l])ouse$/i' => '\1ice',
'/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es',
'/([^aeiouy]|qu)y$/i' => '\1ies',
'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
'/(shea|lea|loa|thie)f$/i' => '\1ves',
'/([ti])um$/i' => '\1a',
'/(tomat|potat|ech|her|vet)o$/i' => '\1oes',
'/(bu)s$/i' => '\1ses',
'/(ax|test)is$/i' => '\1es',
'/s$/' => 's',
);
foreach($rules as $rule=>$replacement)
{
if(preg_match($rule,$name))
return preg_replace($rule,$replacement,$name);
}
return $name.'s';
}
将单词转换为它的复数形式。
prompt()
方法
(可用自 v1.1.9)
public mixed prompt(string $message)
| ||
$message | string | 在用户输入之前输出的内容 |
{return} | mixed | 将整行内容当作字符串返回,如果已经停止输入则返回false。 |
public function prompt($message)
{
if(extension_loaded('readline'))
{
$input = readline($message.' ');
readline_add_history($input);
return $input;
}
else
{
echo $message.' ';
return trim(fgets(STDIN));
}
}
如果readline这个PHP扩展可用,则通过它读取输入的内容,否则通过fgets()来读取。
renderFile()
方法
public mixed renderFile(string $_viewFile_, array $_data_=NULL, boolean $_return_=false)
| ||
$_viewFile_ | string | 视图文件路径 |
$_data_ | array | 要提取的作为视图参数的可选数据 |
$_return_ | boolean | 要返回渲染结果还是直接显示它 |
{return} | mixed | 如果需要的话,则返回渲染结果。否则返回Null。 |
public function renderFile($_viewFile_,$_data_=null,$_return_=false)
{
if(is_array($_data_))
extract($_data_,EXTR_PREFIX_SAME,'data');
else
$data=$_data_;
if($_return_)
{
ob_start();
ob_implicit_flush(false);
require($_viewFile_);
return ob_get_clean();
}
else
require($_viewFile_);
}
渲染一个视图文件。
resolveRequest()
方法
(可用自 v1.1.5)
protected array resolveRequest(array $args)
| ||
$args | array | 命令行参数 |
{return} | array | 动作名字,已经命名的选项(名字=》值),还有没有命名的选项 |
protected function resolveRequest($args)
{
$options=array(); // named parameters
$params=array(); // unnamed parameters
foreach($args as $arg)
{
if(preg_match('/^--(\w+)(=(.*))?$/',$arg,$matches)) // an option
{
$name=$matches[1];
$value=isset($matches[3]) ? $matches[3] : true;
if(isset($options[$name]))
{
if(!is_array($options[$name]))
$options[$name]=array($options[$name]);
$options[$name][]=$value;
}
else
$options[$name]=$value;
}
else if(isset($action))
$params[]=$arg;
else
$action=$arg;
}
if(!isset($action))
$action=$this->defaultAction;
return array($action,$options,$params);
}
解析命令行参数然后决定要运行哪个动作。
run()
方法
public void run(array $args)
| ||
$args | array | 这个命令的命令行参数。 |
public function run($args)
{
list($action, $options, $args)=$this->resolveRequest($args);
$methodName='action'.$action;
if(!preg_match('/^\w+$/',$action) || !method_exists($this,$methodName))
$this->usageError("Unknown action: ".$action);
$method=new ReflectionMethod($this,$methodName);
$params=array();
// named and unnamed options
foreach($method->getParameters() as $i=>$param)
{
$name=$param->getName();
if(isset($options[$name]))
{
if($param->isArray())
$params[]=is_array($options[$name]) ? $options[$name] : array($options[$name]);
else if(!is_array($options[$name]))
$params[]=$options[$name];
else
$this->usageError("Option --$name requires a scalar. Array is given.");
}
else if($name==='args')
$params[]=$args;
else if($param->isDefaultValueAvailable())
$params[]=$param->getDefaultValue();
else
$this->usageError("Missing required option --$name.");
unset($options[$name]);
}
// try global options
if(!empty($options))
{
$class=new ReflectionClass(get_class($this));
foreach($options as $name=>$value)
{
if($class->hasProperty($name))
{
$property=$class->getProperty($name);
if($property->isPublic() && !$property->isStatic())
{
$this->$name=$value;
unset($options[$name]);
}
}
}
}
if(!empty($options))
$this->usageError("Unknown options: ".implode(', ',array_keys($options)));
if($this->beforeAction($action,$params))
{
$method->invokeArgs($this,$params);
$this->afterAction($action,$params);
}
}
执行命令。 默认实现的是解析输入的参数, 然后根据命令请求相关的选项值 调度对应的动作。
usageError()
方法
public void usageError(string $message)
| ||
$message | string | 错误信息 |
public function usageError($message)
{
echo "Error: $message\n\n".$this->getHelp()."\n";
exit(1);
}
显示一个运行错误。 这个方法会终止当前应用的执行。