短小精悍的 PHP MVC架构之URL分发(1)
接上篇 单点入口 。
有个现实的比喻很符合这个MVC模式,那时候应该还用纸写信,大家把信件投递到邮筒,邮递员将信件全部收集起来,然后再根据他们的收件地址进行分发;
如果邮资不够或地址不明确则退回邮件,还有些可能会因为各种原因丢失,比如被人偷了,邮递员不小心寄错了,等等,但是其他的都会到达最后的目的地,
收到信的感觉还是很美妙的。程序设计的思想,我想大都来于现实,来于人们长久积累的经验和智慧;但是高于这些,因为它们是对现实的抽象,在抽象的表象下隐藏了
很多的复杂。 OK,先看框架的目录。
-------------------------------------------华丽的分割线------------------------------------------------------------
MVC架构的文件目录
public/
-------js/
-------css/
-------img/
index.php
.htaccess
app/
-------controller/
-------model/
-------view/
library/
bootstrap.php, controller.class.php, model.class.php, template.class.php, mysql.class.php, arist.php
// 启动文件, 核心的基类文件,数据库类
config/
config.php // 配置文件
tmp/
.htaccess
-------------------------------------------华丽的分割线------------------------------------------------------------
public/index.php 是我们的单入口文件 所有请求都转移到这里分发给不同的控制器,其他都是资源文件;
app/ 是我们的 MVC架构
library/ 是我们的 主要类文件和 一些核心文件
config/ 存放配置文件
tmp/ 存放临时文件 包括log session upload
-------------------------------------------华丽的分割线------------------------------------------------------------
url 分发 (邮件的收集与分发)
index.php
<?php //定义框架路径 define('DS', DIRECTORY_SEPARATOR); define('SYSTEM', dirname(dirname(__FILE__))); //获得url参数 $url = isset($_GET['url']) ? $_GET['url']: ''; //加载启动文件 require_once (SYSTEM . DS . 'library' . DS . 'bootstrap.php');
收集了这些url (信件)后, 我们就需要对他们进行处理.
钩子函数
function Hook() { global $url; // 定义url 的数组 $urlArr = array(); // 分割url 得到url的数组 $urlArr = explode("/",$url); if(!empty($urlArr)){ $controller = array_shift($urlArr); // 得到控制器 $action = array_shift($urlArr); // 得到指令 $stringParameter = $urlArr; // 得到指令参数 $controllerName = $controller; // 得到控制器的名称 $controller = ucwords($controller).'Controller'; $model = trim($controller); // 加载Model // 初始化控制器 $dispatch = new $controller($model,$controllerName,$action); // 判断控制器方法是否存在 if ((int)method_exists($controller, $action)) { // 调用控制器的方法,将参数传递进去 call_user_func_array(array($dispatch,$action),$stringParameter); } else { //不存在该方法的处理 } }else{ // 显示首页 } }
这里有一个关键函数 call_user_func_array(array($dispatch, $action), $stringParameter)
这个函数会调用 $dispatch对象 的 $action 方法,同时以$stringParameter 作为传入参数。简单表达就是 $dispatch->$action($stringParameter);
-------------------------------------------华丽的分割线------------------------------------------------------------
libraray/controller.class.php
这个是我们的核心基类,还是基本阶段,没有扩展很多方法;
<?php class controller{ protected $_model; protected $_controller; // 用于后面加载相应的模板 protected $_action; protected $_template;
// 初始化控制器 加载DB类 控制器和方法 function __construct($model, $controller, $action) { $this->_controller = $controller; $this->_action = $action; $this->_model = $model; $this->$model = new $model; $this->_template = new Template($controller, $action); } // 简单的模板功能 function set($name,$value) { $this->_template->set($name,$value); } function __destruct() { $this->_template->render(); }
// 加载多个 model 对象 function load($modelArray=''){ if(empty($modelArray)){ return false; }else if(is_array($modelArray)){ foreach($modelArray as $model){ $this->$model = new $model; } }else{ $this->$modelArray = new $modelArray; } } }
-------------------------------------------华丽的分割线------------------------------------------------------------
启动文件中有一个 __autoload() 的魔术方法 加载了 所有 library/ 和 app/ 里的类。 所以只需要 $object = new Class(); 就能创建对象。
所有 MVC框架里的 controller 都会继承这个类 以及它的方法;比如当 url 为 http://yoursite.com/mail/send/132921
首先会 分发这个 url, 即 controller = "mail", action = "send", stringParameter =['132921'];
然后初始化这个控制器 $dispatch = new MailController($DB, "mail", '132921');
然后判断这个对象是否具有该方法 method_exists("MailController", "send");
最后回调这个方法 call_user_func_array(array($dispatch,'send'),array('132921'));
class MailController extends Controller{
function send($id){
do something...
}
}
这个 $dispatch 是类 MailController 的一个对象,继承自 Controller,拥有操作数据库的基本对象 $DB, 同时可加载其他的 model;
-------------------------------------------华丽的分割线------------------------------------------------------------
小结:就象邮递员那样,收集了所有的信件,再进行大致分类;下一步,我们要把信发送出去。 下一篇: 短小精悍的 PHP MVC架构之 render Template(2)