沈逸老师PHP魔鬼特训笔记(12\13) --异形

  我们常见的访问约定方式一:/index.php?m=xx&a=oo.其中m和a是固定参数名,

  1、m的值(假设xx是index):代表我们的代码文件名、类名肯定和index有关

  2、a的值:代表代码文件中有个方法叫做OO。

  日常工作中为了规范,我们会把XX设定为一个类。

  常见约定访问方式二:/index.php/xxx/ooo

  其实这个和前面类似,我们可以通过index.php获取当前用户访问的整个url地址,通过各种街区或则$_SERVER['PATH_INFO']后,获取/xxx/ooo这个字符串。而XXX这里代表某类,ooo代表某方法。

  几个注意事项:1、如果你发现你的php不支持path_info请打开。

                        2、如果index.php后面不加path参数,则这个变量是不存在的。因此要做判断。

           3、到了生产环境中可以使用htaccess对所有访问全部重新到path_info 模式的地址。

  以上是常见框架的基本原理,但这不是我们想要的。

  先来看看我们的基本约定:

  1、凡是所谓的控制器,都必须是xxx.class.php这样的形式。

  2、类名和文件名(第一段)必须一致。

  3、在类名上必须写上注释

/**
*@Controller //代表是一个控制器,否则它仅仅是一个普通类
*/

   接下我们开始一个新的实验,在GOD里创建一个新的类叫god_mvc用于处理这些Controller。主要实现下面这些功能:1、构造函数,接受类名参数,用户创建反射。2、判断函数,用于判断是否controller.3、获取所有的方法的注释,解析@RequestMapping(里面的内容)。

<?php

namespace core\frame;
class god_mvc
{
    public $className="";//传入的类名
    public $classComment="";
    public $classMethods=array();
    function __construct($cname)        //接受一个classname(类名)
    {
        $this->className=$cname;

        $f=new \ReflectionClass($cname);
        $this->classComment=$f->getDocComment();
        $this->classMethods=$f->getMethods();//获取类里面所有的方法集合 ,返回一个 方法对象数组
    }
    function isController()
    {
        return preg_match("/@Controller/",$this->classComment);
    }
    function getReqestMapping()
    {
        $result=array();
        foreach($this->classMethods as $method)
        {
            $get_res=$this->genReqestMappingResult($method);
            if($get_res)
            {
                $result=array_merge($result,$get_res);
            }
        }
        return $result;
    }
    function genReqestMappingResult($m)
    {
        //index.php/getme/eme/age
        //@RequestMapping("/getme",Method=GET);
        if(preg_match('/@RequestMapping\("(?<RequestUrl>.{2,50})",Method=(?<RequestMethod>\w{3,8})\);/',$m->getDocComment(),$result))
        {
            return array($result['RequestUrl']=>array(
                'RequestMethod'=>$result['RequestMethod'],
                "Class"=>$this->className,
                'Method'=>$m->getName()
            ));
        }
        return false;
    }
}

?>

  god_frame文件中的compile()方法我们增加获取加载所有类的代码。

function compile(){ //将code里的重复变量读取出来处理掉
       $_files = scandir($this -> project_folder.'/code');
       foreach($_files as $_file){
           if(preg_match("/\w+\.var|func\.php$/i",$_file)){
               require ($this->project_folder.'/code/'.$_file);
               unset($_file);
           }
       }
        unset($_files);//销毁这个无效的变量
        //var_export(get_defined_vars());
        
        $result = '<?php '.PHP_EOL
            .'ectract('.var_export(get_defined_vars(),1).');';
        file_put_contents($this->project_folder."/vars.php",$result);

        $getFunc = get_defined_functions()["user"];
        $getFunc = array_slice($getFunc,6); //去掉GOD程序创建的函数
        $func_set="";
        foreach ($getFunc as $func){
            $f = new \ReflectionFunction($func);
            $start = $f->getStartLine();    //获取该函数的启始行号
            $end = $f->getEndLine();        //获取该函数的末尾行号
            $fileList = file($f-> getFileName());
            $func_set.=implode(array_slice($fileList,$start-1,$end-$start+1));
        }
        
        //生成到项目文件夹,文件名是functions
        file_put_contents($this->project_folder."/functions",'<?php //compiled by GOD '.date('Y-m-d h:i:s').PHP_EOL.$func_set);
       
        /*$f = new \ReflectionFunction('showName');
        $start = $f->getStartLine();    //获取该函数的启始行号
        $end = $f->getEndLine();        //获取该函数的末尾行号
        $fileList = file($f-> getFileName());
        echo implode(array_slice($fileList,$start-1,$end-$start+1));*/
        
        //获取已经加载的所有类
        $class_set=get_declared_classes();       $class_set=array_slice($class_set,array_search(__CLASS__,$class_set)+1);
        $result=array();
        foreach($class_set as $class)
        {
            $mvc=new god_mvc($class);
            if($mvc->isController())
            {
                $mp=$mvc->getReqestMapping();
                $result=array_merge($result,$mp);
            }
        }
        //生成路由文件
        file_put_contents($this->project_folder."/request_route",'<?php return '.var_export($result,1).';');
    }

  然后我来生成路由,把刚才生成所有方法的RequestMapping生成到项目目录下,取个名字叫做request_route.


 

知识点:

反射:1、ReflectionClass :对“类”进行反射,并获取相关信息。

2、学习获取类“注释”的方法

$f = new ReflectionClass(类名);

$doc = $f->getDocComment();  //获取注释

echo $doc   

3、get_declared_classes()

4、__class__ PHP魔力变量 可以获取当前类名

 

posted @ 2016-09-12 16:28  前进的卒子  阅读(270)  评论(0编辑  收藏  举报