PHP框架对地址进行Dispatch的思考
如何设计自己的一个MVC框架?
这个问题困扰了我很久,我相信大多数童鞋也都是用流行的哪些框架都很溜了(指逻辑控制,DB操作以及一些validation等),但真正思考自己的MVC框架,思路不一定很清晰,或者说多多少少会做错路。
在下也花了一些(很长~)时间来思考这个问题,总结一下思路,对Layman的我们来说一起借鉴下。
基本思路:
1.任何框架的使用开发的WEB应用,最后都是通过用户在浏览器输入URL地址才能访问,URL长什么样,这是切入点;
2.URL有多种模式,最佳实践的应该是pathinfo,因为对搜索引擎友好,主要还是直观书写方便;
3.在单一入口index.php中首先进行处理,获取到这个request_url,这之后可以开始框架流程了;
到此后面的思路就是怎么对request_url各种截断,并对应来获取到Controller类和调用类中的Action了,
这里展示一个封装的application类,在入口文件中先实例化并调用dispatch方法来进行路由分发请求,实现框架流程。
1 <?php 2 namespace Framework; 3 4 class Application 5 { 6 public $base_dir; 7 protected static $instance; 8 9 public $config; 10 11 protected function __construct($base_dir) 12 { 13 $this->base_dir = $base_dir; 14 $this->config = new Config($base_dir.'/configs'); //读取一些配置文件信息 15 } 16 17 static function getInstance($base_dir = '') 18 { 19 if (empty(self::$instance)) 20 { 21 self::$instance = new self($base_dir); 22 } 23 return self::$instance; 24 } 25 26 function dispatch() 27 { 28 // $uri = $_SERVER['SCRIPT_NAME']; 29 $uri = $_SERVER['PATH_INFO']; 30 list($c, $a) = explode('/', trim($uri, '/')); 31 32 $c_low = strtolower($c); 33 $c = ucwords($c); 34 $class = '\\App\\Controller\\'.$c; //这里是实际的控制器类,它会继承下面的控制器核心类 35 $obj = new $class($c, $a); 36 37 $return_value = $obj->$a(); //这里实现方法调用 38 39 } 40 }
来看看Controller类怎么实现:
1 <?php 2 namespace Framework; 3 4 abstract class Controller 5 { 6 protected $data; 7 protected $controller_name; 8 protected $action_name; 9 protected $template_dir; 10 11 function __construct($controller_name, $action_name) 12 { 13 $this->controller_name = $controller_name; 14 $this->action_name = $action_name; 15 $this->template_dir = Application::getInstance()->base_dir.'/templates'; //视图模板,这个路径可以换 16 } 17 18 function assign($key, $value) 19 { 20 $this->data[$key] = $value; 21 } 22 23 function display($file = '') 24 { 25 if (empty($file)) 26 { 27 $file = strtolower($this->controller_name).'/'.$this->action_name.'.php'; 28 } 29 $path = $this->template_dir.'/'.$file; 30 extract($this->data); 31 include $path; 32 } 33 }
到此就是基本的MVC设计思路了,后面补充上DB的操作,顺便运用下工厂模式。