现在的位置: 首页 > 综合 > 正文

PHP框架开发:五、视图(View)的实现

2013年04月06日 ⁄ 综合 ⁄ 共 3241字 ⁄ 字号 评论关闭

视图层又叫表现层,也有人叫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";
        }
    }
    ?>

    这个LQP_Controller 类是每个控制器的父类,其中会提供一些常用的方法,目前有三个主要方法,lqp_init、init、loadView,其中init为一个“事件方法”,当程序开始执行时总会先执行init中的代码,子类可以覆盖这个方法以添加一些需要“事先执行”的代码;lqp_init是框架控制器的初始化方法,loadView用于加载视图,你不应该覆盖这些方法,也不应在你的代码中调用这些方法,此方法会有框架在Rewrite时自动调用,框架调用原理如下:

      a) 修改Loader.php文件,加入一句:require_once 'Controller.php';
      b) 修改HomeController.php文件,让类HomeController继承自LQP_Controller,如下:
      <?php
      class HomeController extends LQP_Controller
      {
           function indexAction()
           {
           }
      };
      ?>

      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);
          }

          然后修改disponse方法为如下形式:

          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);
          }

          其中修改的代码已标出,关于$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

    抱歉!评论已关闭.