自己动手写个小框架之二
麻雀虽小五脏俱全,我们给小框架做些布局如图所示
其中library为公共类,kernel为框架运行所需的基础类,Controller为控制类,libs和tpls则是smarty运行所需的核心类及文件,Config为配置内容如后续数据库连接配置文件等。
框架大致运行流程为,router路由解析后调用相应的Controller类并执行调用的action方法,然后绑定数据到tpls里相应的tpl模板文件进行显示。
其中,程序的入口为index.php文件,主要对路由地址进行解析。假设地址为http://localhost/dluf/index.php/default/index/dluf,那么default表示控制类defaultController.php,index表示该控制类里的indexAction函数,dluf则是传递的参数可以没有。(为方便起见,指定这为框架的统一路由地址格式)
入口index.php文件为
1 <?php 2 require_once (__DIR__ . '\startup.php'); 3 $app_path = str_replace($_SERVER['DOCUMENT_ROOT'], "", __FILE__); 4 $se_string = str_replace($app_path, "", $_SERVER['REQUEST_URI']); 5 $register = new Register(); 6 $loader = new Loader($register); 7 $router = new router($se_string, $loader); 8 //echo print_r($router, true); 9 //exit(); 10 try { 11 $router->loadTpl(); 12 } catch (Exception $exception) { 13 echo "INFO:" . $exception; 14 } 15 ?>
$se_string为需要解析地址,声明一个路由对象$router,并绑定一个Loader类实体$loader来解析$se_string。$loader实体用到一个注册对象,为一个键值存储类。register.php类为:
1 <?php 2 final class Register{ 3 private $data = array(); 4 5 public function get($key){ 6 return (isset($this->data[$key])?$this->data[$key]:NULL); 7 } 8 9 public function set($key,$value){ 10 $this->data[$key] = $value; 11 } 12 13 public function has($key){ 14 return isset($this->data[$key]); 15 } 16 17 } 18 ?>
需要调用的加载类在startup.php里添加
1 <?php 2 3 //library 4 require_once (__DIR__ . '\library\router.php'); 5 //kernel 6 require_once (__DIR__ . '\kernel\autoload.php'); 7 require_once (__DIR__ . '\kernel\register.php'); 8 require_once (__DIR__ . '\kernel\request.php'); 9 require_once (__DIR__ . '\kernel\baseController.php'); 10 ?>
路由类router.php,这里简单起见从数组内容个数判断格式是否正确,可以加个方法通过正则表达式对初始地址字符进行过滤。
1 <?php 2 3 class router { 4 5 private $url; 6 private $urlarr; 7 private $argsarr; 8 private $classname; 9 private $method; 10 private $loader; 11 private $urltag; 12 13 public function __construct($url, $loader) { 14 $this->url = $url; 15 $temp = explode("/", $this->url); 16 unset($temp[0]); 17 foreach ($temp as $key=>$value) { 18 $this->urlarr[] = $value; 19 if($key >4){ 20 $this->argsarr[] = $value; 21 } 22 } 23 $this->loader = $loader; 24 if(count($this->urlarr)>3){ 25 $this->classname = $this->urlarr[2]; 26 $this->method = $this->getMethod(); 27 }else{ 28 $this->urltag = "default"; 29 } 30 } 31 32 private function checkUrl($url){ 33 $tag = true; 34 if(preg_match("/(\.css)*(\.jpg)*/", $url)){ 35 $tag = false; 36 } 37 return $tag; 38 } 39 40 public function getController() { 41 $this->classname = $this->urlarr[2]; 42 return $this->classname; 43 } 44 45 private function getMethod() { 46 if(isset($this->urlarr[3]) && !empty($this->urlarr[3])){ 47 $this->method = $this->urlarr[3] . "Action"; 48 }else{ 49 $this->method = "indexAction"; 50 } 51 return $this->method; 52 } 53 54 public function loadTpl() { 55 //判断地址解析后是否符合标准 56 if($this->urltag != "default"){ 57 $this->loader->register('controller', $this->classname); 58 $re = new ReflectionClass($this->classname . "Controller"); 59 $controller = $re->newInstance(); 60 // echo print_r($this->urlarr,TRUE); 61 if(isset($this->method)){ 62 $method = $re->getMethod($this->method); 63 }else{ 64 $method = $re->getMethod("indexAction"); 65 } 66 $method->invoke($controller, $this->argsarr); 67 }else{ 68 echo "welcome use this system!"; 69 } 70 71 } 72 73 } 74 75 ?>
整个流程的执行由index.php中的$router->loadTpl()启动。
在系列三中,会对Loader类进行介绍。