我们常见的访问约定方式一:/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 coreframe; 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魔力变量 可以获取当前类名