在开发过程中,经常需要有每隔多少分钟就执行一次任务的需求,本文讲的就是在yaf下使用命令行的形式(cli模式)定时运行脚本文件,换而言之就是在cli模式下运行模块控制器的方法。例如在linux环境下通过/usr/local/php/bin/php /home/wwwroot/swoole-yaf/cli.php Cli~Test/index这条指令就可以运行我的Cli模块下的Test控制器中的index的方法。这是实现定时运行脚本的前提。
原理就是在通过解析指令的,将模块名,控制器名,方法名写入请求的路由中,这样就通过bin指令可以访问到我们项目下的方法。其中最重要的就是yaf下的Yaf_Request_Simple,新建一个路由请求,打印出该实例对象的所有参数,如下所示:
Yaf_Request_Simple Object
(
[module] =>
[controller] =>
[action] =>
[method] => CLI
[params:protected] => Array
(
)
[language:protected] =>
[_exception:protected] =>
[_base_uri:protected] =>
[uri:protected] =>
[dispatched:protected] =>
[routed:protected] =>
)
模块名,控制器名,方法名,如果有参数还要写入参数,配置路由uri,然后就可以发起路由请求了。
新建一个文件cli.php,该文件就是将bin指令的参数进行解析并写入新请求的路由中。
<?php
/**
* 使用方法:/usr/local/php/bin/php /home/wwwroot/swoole-yaf/cli.php Cli~Test/index
* 第一个参数是php的bin指令 第二个参数是运行的文件路径 第三个参数是模块名~控制器名/方法名
* 第三个的参数异常重要 包括文件名控制器名方法名的大小写在下面代码进行了处理的
*/
define('APPLICATION_PATH',dirname(__FILE__));
date_default_timezone_set("Asia/Shanghai");//设置时区
$app = new Yaf_Application(APPLICATION_PATH . '/conf/application.ini','cli' );//加载配置文件
$req = new Yaf_Request_Simple(); //新建一个路由请求
//print_r($req);
if ( $req->isCli () ) {
/**
* /usr/local/php/bin/php /home/wwwroot/swoole-yaf/cli.php Cli~Test/index
* $argc $argv 是php自带的两个参数
* $argc是获取cli模式下参数的个数 例如上面指令就是两个
* $argv是获取参数的值 是一个数组
*/
global $argc, $argv;
if ( $argc > 1 ) {
$module = '';
$uri = $argv [1];//获取到Cli~Test/index
if ( preg_match ( '/^[^?]*~/i', $uri ) ) {
list ( $module, $uri ) = explode ( '~', $uri, 2 );//将获取的值按~分割成两个
}
$module = strtolower( $module ); //获取到模块Cli
$modules = Yaf_Application::app()->getModules ();//获取application.ini配置文件下的合法模块
if ( in_array ( ucfirst ( $module ), $modules ) ) { //判断Cli模块是否在配置文件中已经配置
$req->setModuleName ( $module );//在路由中的设置模块名
}
if ( false === strpos ( $uri, '?' ) ) {//解析uri是否带有参数
$args = array ();
} else {
list ( $uri, $args ) = explode ( '?', $uri, 2 );
parse_str ( $args, $args );
}
foreach ( $args as $k => $v ) {//将参数值写入请求路由中
$req->setParam ( $k, $v );
}
$req->setRequestUri ( $uri ); //在路由中设置uri
if ( $req->isRouted () && ! empty ( $uri ) ) {//判断路由是否合法,uri是否非空
if ( false !== strpos ( $uri, '/' ) ) {
list ( $controller, $action ) = explode ( '/', $uri );
$req->setActionName ( $action );//在路由中设置方法名
} else {
$controller = $uri;
}
$req->setControllerName ( ucfirst ( strtolower ( $controller ) ) );//在路由中设置控制器名
}
}
$app->bootstrap()->getDispatcher()->flushInstantly( true )->dispatch( $req ); // 如果打开flushIstantly, 则视图渲染结果会直接发送给请求端而不会写入Response对象
} else {
exit;
}
然后在linux运行指令就可以了,注意要在application.ini配置你的模块名,还有需要注意新建的模块名,控制器名,方法名是否合法,你也可以通过修改Cli.php配置自己习惯的命名规范。
/usr/local/php/bin/php /home/wwwroot/swoole-yaf/cli.php Cli~Test/index
然后在server回调函数Start中调用方法swoole_timer_tick定时器方法定时调用shell脚本即可:
$http->on('Start',function(){
swoole_timer_tick(1000,function(){//1000是1000毫秒的意思
$shell = '/usr/local/php/bin/php /home/wwwroot/swoole-yaf/cli.php Cli~Test/index';
var_dump(shell_exec($shell));
});
});
以上就完成了swoole+yaf执行定时任务的操作了。