> YII 类库手册 > CConsoleCommand
system.console
继承 abstract class CConsoleCommand » CComponent
子类 CHelpCommand
源自 1.0
版本 $Id: CConsoleCommand.php 3548 2012-01-24 11:42:59Z mDOMba $
源码
CConsoleCommand代表一个可执行的控制台命令。

它的工作原理跟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 要复制的文件列表(名字=》说明)。 在复制过程中,数组键名是显示出来的名字,数组键值是复制的 文件的规格。每一个数组值一定是以下的数组结构:
  • 源:必须提供, 要复制的源文件/目录的完整路径
  • 目录:必须提供,要复制去的目标文件/目录的完整路径
  • 回调: 可选,当复制文件的时候要调用的回调函数。 这个回调函数应该如下面定义:
      function foo($source,$params)
      
    $source参数是源文件路径, 函数返回的内容会被保存到目标文件。
  • 参数:可选,要传递给回调的参数。
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);
}

显示一个运行错误。 这个方法会终止当前应用的执行。