[PHP] 命令行执行整合pathinfo模拟定时任务

命令行模式下,根据传参,调用不同控制器。控制器中根据配置定时执行指定方法

Application.php

<?php
class Application{
    public static function main(){
        header("content-type:text/html;charset=utf-8");
        self::register();
        self::commandLine();
        self::pathInfo();
    }
    //自动加载
    public static function loadClass($class){
        $class=str_replace('\', '/', $class);
        $dir=str_replace('\', '/', __DIR__);
        $class=$dir."/".$class.".php";
        require_once $class;        
    }
    //命令行下
    public static function commandLine(){
        if(php_sapi_name()=="cli"){
            $_SERVER['PATH_INFO']="";
            foreach ($_SERVER['argv'] as $k=>$v) {
                if($k==0) continue;
                $_SERVER['PATH_INFO'].="/".$v;
            }
        }
    }
    //pathinfo处理
    public static function pathInfo(){
        if(isset($_SERVER['PATH_INFO'])){
            $pathinfo=array_filter(explode("/", $_SERVER['PATH_INFO']));
            for($i=1;$i<=count($pathinfo);$i++){
                $key=isset($pathinfo[$i]) ? $pathinfo[$i] : '';
                $value=isset($pathinfo[$i+1]) ? $pathinfo[$i+1] :"";
                switch ($i) {
                    case 1:
                        $_GET['m']=ucfirst($key);
                        break;
                    case 2:
                        $_GET['c']=ucfirst($key);
                        break;
                    case 3:
                        $_GET['a']=$key;
                        break;
                    default:
                        if($i>3){
                            if($i%2==0){
                                $_GET[$key]=$value;
                            }
                        }
                        break;
                }
            }
        }
        $_GET['m']=!empty($_GET['m']) ? ucfirst($_GET['m']) : 'Index';
        $_GET['c']=!empty($_GET['c']) ? ucfirst($_GET['c']) : 'Index';
        $_GET['a']=!empty($_GET['a']) ? $_GET['a'] : 'index';
        $class="\Controller\{$_GET['m']}\{$_GET['c']}";
        $controller=new $class;
        $controller->$_GET['a']();
    }
    //致命错误回调
    public static function shutdownCallback(){
        $e=error_get_last();
        if(!$e) return;
        self::errorHandler($e['type'],'<font color="red">Fatal Error</font> '.$e['message'],$e['file'],$e['line']);
    }
    //错误处理
    protected static function myErrorHandler($errno,$errstr,$errfile,$errline){
        list($micseconds,$seconds)=explode(" ",microtime());
        $micseconds=round($micseconds*1000);
        $micseconds=strlen($micseconds)==1 ? '0'.$micseconds : $micseconds;
        if(php_sapi_name()=="cli"){
            $break="
";
        }else{
            $break="<br/>";
        }
        $mes="[".date("Y-m-d H:i:s",$seconds).":{$micseconds}] ".$errfile." ".$errline." line ".$errstr.$break;
        echo $mes;        
    }
    //注册
    public static function register(){
        error_reporting(0);
        set_error_handler(function($errno,$errstr,$errfile,$errline){
            self::myErrorHandler($errno,$errstr,$errfile,$errline);
        });
        register_shutdown_function(function(){
            self::shutdownCallback();
        });
        spl_autoload_register("self::loadClass");
    }
}

Application::main();

ControllerClientCron.php

<?php
namespace ControllerClient;

class Cron{
    private $second=0;
    private $tasks=array(
        array("duration"=>5,"method"=>"doSomething"),
        array("duration"=>2,"method"=>"doSomething2"),
    );
    public function index(){
        while (true) {
            sleep(1);
            $this->second++;
            foreach($this->tasks as $task){
                if($this->second%$task['duration']==0){
                    $this->$task['method']();
                }
            }
        }
    }
    public function doSomething(){
        echo "[".date("Y-m-d H:i:s",time())."] doSomething1 ok!
";
    }
    public function doSomething2(){
        echo "[".date("Y-m-d H:i:s",time())."] doSomething2 ok!
";
    }
}

效果:

方法doSomething每隔2秒执行一次

方法doSomething2每隔5秒执行一次

现在执行其他方法是同步的,可以再优化成开新线程执行这些方法,就不会阻塞主线程的定时了

原文地址:https://www.cnblogs.com/taoshihan/p/5763198.html