在开发过程中,经常需要有每隔多少分钟就执行一次任务的需求,本文讲的就是在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/indexif ( 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 ); //在路由中设置uriif ( $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执行定时任务的操作了。