您的位置:首页 > 编程语言 > PHP开发

PHP Yii 命令行程序以及定时任务详解

2015-12-07 15:45 671 查看
为啥要编写命令行程序?

命令行程序通常是一个脚本,但是PHP Yii 是web开发语言,如何能开发脚本程序?

所以,首先我们要明白使用PHP Yii 编写脚本语言的目的和原理。



目的

设想这么一个场景,你开发了一个电子商务网站,在测试阶段,你希望模拟用户的下单操作。或者你开发了一个类股票网站,在测试阶段,你需要模拟用户的委托买入、卖出操作,并撮合用户的买入和卖出。毕竟,如果想模拟大量用户的操作,而通过手动在数据库中添加测试数据,这工作量有点大。

所以,编写Yii 脚本的目的是,通过运行脚本,自动生成用户的下单操作。这个类似于一个服务器端的程序,可以用JAVA写,但是我们是PHP程序员啊,当然用PHP实现了。

原理和流程

使用PHP Yii 编写脚本的程序的基本原理是这样的:

(1)编写一个Command类,类名和文件名以Command为后缀,同时继承父类CConsoleCommand,文件存放在工程下的protected/commands/目录下,例如:

<span style="font-family:Tahoma;font-size:12px;">class TestCommand extends CConsoleCommand</span>




(2)编写Command类的动作,类似控制器的动作,动作名需要以action为前缀,例如:

<span style="font-family:Tahoma;font-size:12px;">public function actionTest(){
echo "command test successfully.";
}</span>


echo的内容会打印在Windows DOS或Linux的命令行程序页面上。完整的命令类如下:

<span style="font-family:Tahoma;font-size:12px;"><?php
class FarmProduceMatchCommand extends CConsoleCommand
{

/**
* Execute the action.
* @param array command line parameters specific for this command
*/</span>
<span style="font-family:Tahoma;font-size:12px;">/*
public function run($args)
{
if(!isset($args[0]))
$this->usageError('please input params.');
echo('you input :\n');
var_dump($args);
}
*/
public function actionTest(){
echo "command test successfully.";
}
}</span>


(3)如何运行自定义的Command类和动作呢,很简单,不需要配置PHP和Yii的环境和变量。打开Dos(windows系统)或Terminal(Linux系统),在命令行,将目录定位到你的yii工程的protected目录,该目录下有yiic命令程序。比如,我的工程目录在“C:\xampp\htdocs\syjjq2”,“syjjq2”就是我的yii工程。在命令行将目录定位到syjjq2工程下的protected目录,工程目录结构如下:





为什么要调用你工程下的protected目录的yiic.bat,而不直接调用Yii框架目录下的yiic.bat,主要原因是你的工程下的protected下的yiic.bat能自动识别该工程中的命令类和动作。而yii框架目录下的则找不到你自定义的命令。

下面我们操作一下在命令行调用自定义的动作,命令格式是:【yiic 自定义命令类名称 动作名称】。需要注意的是,这里的命令类名称和动作名称,与控制器名称和动作名称一样,可以把命令类想象成一个控制器,所以,命令名就是命令类的类名去掉command后缀,然后第一个字母小写,动作名称就是动作函数的名称去掉action前缀,然后第一个字母小写即可。比如,我想看看我自定义的FarmProduceMatchCommand命令类有几个动作,可以使用【yiic
自定义命令类名称】:



其实这种命令写法,没有指定要执行该命令类的哪一个动作,默认会执行名称为index的动作,但是,我们这个类没有名为index 的动作,所以它报了一个错,同时,会把该命令类下所有的动作都罗列出来。

好了,那我们正式执行我们自定义的FarmProduceMatchCommand命令类的test动作:



到此,我们自定义的命令类和动作就执行成功了!

进阶

(1)run函数。

Command类的起始函数为run,该函数继承自CConsoleCommand类,当你自定义的Command类重载run函数的时候,其他的自定义动作对于命令行来说都会失去效果,即当run函数存在的时候,无法在命令行调用其他的自定义动作,因为run函数会拦截其他动作的调用,把调用的动作认为是run函数的传入参数。比如,我们把上面的FarmProduceMatchCommand类中的run函数部分的注释去掉,你再在命令行运行刚才的【yiic
farmProduceMatch test】命令试试,执行结果如下:



看到没,你希望执行的是farmProduceMatch的test动作,结果执行的是run函数,并且,你输入的动作名test被认为是run函数的一个传入参数。

run函数接收一个参数数组,你可以在命令行输入多个参数,以空格隔开即可,如:

yiic farmProduceMatch param1 param2 param3 param4……

也就是说,如果你的命令类中只有一件事情要处理,可以直接在run函数中编写。但通常来说,业务比较复杂的情况下,就需要在一个命令类中执行多个动作了,比如:生成委托买入订单动作,生成委托卖出订单动作,生成撮合委托订单动作……当你需要编写多个动作,并且分别需要在命令行中调用某个动作的时候,就需要把这个run函数给注释掉了。

(2)动作函数如何在命令行传入参数。

我们把上面的test动作稍微改一下:

<span style="font-family:Tahoma;font-size:12px;">public function actionTest($param1, $param2){
echo "command test successfully. you have input:$param1, $param2";
}</span>


我给test函数添加了两个参数,并在屏幕上打印出来用户输入的两个参数:



在命令行传入参数的时候要遵循格式【yiic 自定义命令类名称 动作名称 --参数1=参数值 --参数2=参数值 --参数3=参数值……】。

即要在你的动作参数名钱加两个‘-’,后面跟上赋值即可。多个参数赋值使用逗号隔开即可。

(3)执行yiic时报错。

执行yiic命令时,如果报错的话,例如php不是内部或外部命令之类的,你需要修改一下protected/yiic.bat文件,原始内容如下:

<span style="font-family:Tahoma;font-size:12px;">@echo off

rem -------------------------------------------------------------
rem  Yii command line script for Windows.
rem  This is the bootstrap script for running yiic on Windows.
rem -------------------------------------------------------------

@setlocal

set BIN_PATH=%~dp0

if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe

"%PHP_COMMAND%" "%BIN_PATH%yiic.php" %*

@endlocal</span>


你要把“PHP_COMMAND=php.exe”改成你实际的PHP路径。比如我用的是集成PHP环境xampp,放在C:目录下的,那么php目录在“C:\xampp\php”。改成“PHP_COMMAND=C:\xampp\php\php.exe”即可。

(4)使用yiic命令,找不到自定义的命令类和动作。

其实这个很简单,前面我已经提到过了。自定义的command类,要放在/protected/commands/目录下;运行的yiic命令为/protected/yiic.bat文件,不要运行Yii framework下的yiic;检查自定义command类的文件名称和类名称命名是否规范,以及动作的命名是否规范。

(5)如何配置command类的相关配置项

Yii框架分为两个部分,一个是web,一个是cli,即命令行程序。cli模式有单独的配置文件:“/protected/config/console.php”。比如,你的自定义command类中,需要调用数据库,模型类,或者其他模块的文件,就需要在console.php中配置了。配置方法和main.php中一样。

高级

上面的例子我们已经讲了,如何编写命令类和动作,如何运行,等等。到此,我们也大概了解了yii的命令行运行机制,其实就是通过yiic命令调用某个命令类和动作。

下面,我们设想如下情景,我们需要模拟不同的用户在不同的时间进行下单操作。如果只是产生一条测试数据的话,我们直接在命令行中执行一下该动作即可,但是模拟不同时间不同用户的情况的话,我们就需要定时执行某个动作了。

定时执行某个动作,我们可以不用cli,直接写个控制器,然后写个动作,动作中有个死循环,每隔多长时间执行一次某个函数来生成一条测试数据。

但这种方法我觉得太过于笨重了,毕竟php属于web语言,让他执行一个服务端程序的事情确实有些不妥。

如果了解windows脚本或linux shell的同学应该可以想到这种方法,把命令行执行自定义命令类和动作的指令写入一个文本文件,然后将文件名的后缀改成*.bat(Windows系统),这样我们就创建了一个脚本,双击执行这个脚本,就会自动执行生成一条模拟用户下单的测试数据,就不用我们在命令行输入命令了。

比如,我创建一个test.bat文件,使用记事本打开,输入以下内容:

C:\xampp\htdocs\syjjq2\protected\yiic farmProduceMatch
test --param1=hello --param2=world

输入好后保存,我们就创建好了这个脚本。

如何自动执行这个脚本呢?我们可以创建一个系统计划任务,定时执行这个脚本。以下以Win7为例,讲解如何创建定时计划任务来定时执行我们的脚本。

首先,右键“计算机”,选择“管理”菜单,进入“计算机管理”页面:



在左栏,选择“计划任务程序”,然后在右栏选择“创建任务…”,打开创建任务对话框。

(1)创建任务-常规



任务的名称和描述可以随意写。安全选项和配置根据自己的需求写。其中,安全选项如果选择“只在用户登录时运行”,如果你的电脑又没设置密码,不需要登录,你的定时任务就永远无法执行了,所以,我选择第二个。

(2)创建任务-触发器



打开“触发器”选项卡,点击“新建…”按钮,我们新建一个触发器。触发器的内容可以根据你的需求填写,上图中,我创建了一个从当前时间开始每隔5分钟执行一次脚本的触发器。“启用”一定要勾上啊。

(3)创建任务-操作



打开“操作”选项卡,点击“新建…”按钮,新建一个操作。操作类型为“启动程序”,然后选择要执行的脚本文件的位置。如果要添加起始参数的话,可以在该页面进行配置。

(4)创建任务-条件



打开“条件”选项卡,根据自己的需求选择。

(4)创建任务-设置



打开“设置”选项卡,根据个人需求进行配置。

然后就可以点击“确定”按钮保存该任务计划了。

到此,任务计划已经创建完成,但是还没有结束。点击确定按钮创建任务计划成功后,在任务计划页面我们会看到我们创建的任务:



可以看到,我们创建的任务已经在任务列表中了,但是“状态”是“准备就绪”,也就是说任务还没开始运行。选择我们创建的任务,在右栏中选择“运行”,再看看我们创建的任务状态,变成“正在运行”就说明我们已经创建并运行任务计划成功了!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: