视图层又叫表现层,也有人叫UI,几年前当MVC开发模式在Web开发中并不是很流行时,人们最常讨论的是“代码逻辑与Html界面的分离”,PHP中最有代表可能是Smarty模板技术吧,因为当时的Web开发并不需要现在那么复杂,随着越来越多“软件Web化”,代码逻辑越来越复杂,MVC模式也就越来越被人重视了。
在我们这个框架中视图采用的是PHP解析引擎,因为其实现简单,效率较高,且较通用,你可以在里边写任意可执行的PHP代码,就像没有用框架一样。当然,你若喜欢Smarty那种模板风格的“标签”式视图,也可以替换掉相应的代码,自己实现之(对模板的解析就是个查找替换的过程而已)。
上一节中我们创建了HomeController控制器,并添加了index动作,现在让我们先为它建立对应的视图:
- 在views下创建home文件夹,在home下创建index.php文件 (注意大小写)
index.php是一个标准的Html文件,内容如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>页面标题</title> </head> <body> 这是home/index视图 </body> </html>
上一节中我们已经能够通过 http://www.example.com/home/index 来执行HomeController中的indexAction方法了,如果让程序执行完这个方法后转向视图的执行呢?如何把在动作中向视图传递值呢?为了达到我们的目的,下面需要创建一个LQP_Controller框架类:
- 在library/LQP下创建文件Controller.php,内容如下:
<?php /** * 控制器的基类 * * @author z */ class LQP_Controller { private $_controllerName, $_viewName; public function lqp_init($controllerName,$viewName) { $this->_controllerName = $controllerName; $this->_viewName = $viewName; $this->init(); } function init() { //由子类去实现 } function loadView($viewData) { if(empty($this->_viewName)) return ; require_once APP_VIEW_DIR."/{$this->_controllerName}/{$this->_viewName}.php"; } } ?>
-
a) 修改Loader.php文件,加入一句:require_once 'Controller.php';
b) 修改HomeController.php文件,让类HomeController继承自LQP_Controller,如下:
c) 修改Rewrite.php文件,添加一个disponseView方法用来作为解析视图的入口函数:
private function disponseView(LQP_Controller $controller, $actionReturnData) { if(is_bool($actionReturnData)) $controller->setView($controller->getViewName().($actionReturnData?'Success':'Fail')); $controller->loadView($actionReturnData); }
function dispatch() { $controllerClassName = ucfirst($this->_controllerName)."Controller"; $controllerFile = APP_CONTROLLER_DIR."/$controllerClassName.php"; require_once $controllerFile; $controller = new $controllerClassName(); $controller->lqp_init($this->_controllerName,$this->_actionName); $action = $this->_actionName; $action .= "Action"; $actionReturnData = $controller->$action(); $this->disponseView($controller, $actionReturnData); }
这样修改之后当我们访问http://www.example.com/home/index 时将会看到“这是home/index视图”的信息,下面说一下控制器与视力间是如何传值的。
如果你用过PHP框架,应该会知道,当在动作中写下如:$this->varName = “abc”; 的代码时,在视图就可以使用$this->varName或$varName之类的变量取到设定的值,这是如何实现的呢?如果你对PHP的require / include机制比较了解,在查看了上面的代码后应该不难理解了:我们使用LQP_Controller中的loadView方法加载视图,而每个控制器都继承自LQP_Controller,自然控制器类的中定义的“属性”就可以被访问到了。而不加$this的形式一般都是对控制器对象使用了php的extract函数。个人认为那样没什么必要,故本框架中将采用$this->varName的形式,当然也有例外,比如“返回值”,后面会讲到。
下面可以做个传值的试验:
- 在HomeController中的indexAction方法里写上一行代码:
$this->hello = “hello world”; - 在views/home/index.php的body中加入一行:
<?php echo $this->hello ?> - 访问http://www.example.com/home/index看看是不是会输出“hello world”呢?
总节一下,与上一节类似本节也只是简单讲解了视图的实现原理,后面的章节中会逐渐加入一些“新鲜元素”,只能加入这些元素,使用框架开发才真正的带给你好处。
下一节会讲讲框架中的HttpRequest与HttpResponse,做过.net/java开发的对这两个类一定不会陌生,呵呵
本节代码下载:http://cid-8248e4adbf2b92f3.office.live.com/self.aspx/.Public/Lesson%205.rar