明晰php Zend Framework中的render

搞asp.net mvc时对php mvc发生兴趣 看了看Zend Framework(下简称ZF) 
可以对比理解mvc
对一个比较核心的函数render很是迷惑了一阵 记录下明晰过程

通常在我们利用ZF实现php的mvc时,最关键的地方当然是Controller类的各种action方法,在action方法中,我们确定及输出内容. 在类 abstract class Zend_Controller_Action 中的dispatch方法你可以发现这一行 $this->$action();

那么如何确定及输出内容呢,就是进行render了,不过这个render却是有好几个的,下面列出这几个情形
复制代码
 1 <? php
 2 class  IndexController  extends  Zend_Controller_Action
 3 {
 4      public   function  contactAction()
 5     {
 6          // $this->render("index");
 7         //$this->render();
 8         //$this->renderScript("sidebar.phtml");
 9
10
11         //$this->_helper->viewRenderer("sidebar");
12
13         //$this->view->render("sidebar.phtml");
14         //$this->view("sidebar"); 
15
16     }
17 }
18 ?>
复制代码

总结下来,似乎就是这三中render了(欢迎补充)

1.自身render

先看第一种
    // $this->render("index");
   //$this->render();
   //$this->renderScript("sidebar.phtml");
这是直接使用Zend_Controller_Action类的render方法
第一句是render了另一个action所对应的视图(看清了 是render那个action对应的视图 而不是执行那个action!)
第二句式render本action对应的视图,这个有什么意义呢(因为很多情形你看不到这个写法的),这个下面再说.
第三句是render特定的视图文件,这里你可能认为前两个方法实际是调用了这个renderScript,其实不是如此.
下面就阐述一下.顺便解释第二句的原因.
Zend_Controller_Action类的render方法中其实是有两个分支的 如下render函数代码
复制代码
 1      public   function  render( $action   =   null ,   $name   =   null ,   $noController   =   false )
 2     {
 3          if  ( ! $this -> getInvokeArg( ' noViewRenderer ' &&   $this -> _helper -> hasHelper( ' viewRenderer ' )) {
 4              return   $this -> _helper -> viewRenderer -> render( $action ,   $name ,   $noController );
 5         }
 6
 7          $view     =   $this -> initView();
 8          $script   =   $this -> getViewScript( $action ,   $noController );
 9
10          $this -> getResponse() -> appendBody(
11              $view -> render( $script ) ,
12              $name
13         );
14     }
复制代码
可以看到一种情形是利用(代理)了视图助手类(viewRenderer)的render方法
另一种是禁用助手时的情形 就得亲自上阵了,这也就是render()出现的原因,你禁用了视图助手后要输出本action对应视图内容可以使用render()来完成

2.通过视图助手viewRenderer

上面说起了视图助手,那我们来看action中的第二个片段,正是借助视图助手来进行
    //$this->_helper->viewRenderer("sidebar");
实际上这里这句话并不是render内容,而是指定了要render哪个视图,参考Zend_Controller_Action_Helper_ViewRenderer类的这个函数
1      public   function  direct( $action   =   null ,   $name   =   null ,   $noController   =   null )
2     {
3          $this -> setRender( $action ,   $name ,   $noController );
4     }
那么输出呢 是怎么输出的?
可以在 $this->_helper->viewRenderer("sidebar");  后直接调用$this->render();即可.
但是实际上你完全不用调用,只写那一句就行.
你不写render的时候,视图助手会来替你完成.在Zend_Controller_Action类中的dispatch方法中有这么一句
$this->_helper->notifyPostDispatch();
_helper是什么? 是一个Zend_Controller_Action_HelperBroker类 ,其中有这个方法 
1      public   function  notifyPostDispatch()
2     {
3          foreach  (self :: getStack()  as   $helper ) {
4              $helper -> postDispatch();
5         }
6     }

可以看到调用了其中各个助手的 postDispatch ();
viewRenderer 正是其中的一个助手,其 postDispatch 方法如下
1      public   function  postDispatch()
2     {
3          if  ( $this -> _shouldRender()) {
4              $this -> render();
5         }
6     }
正是在这里视图助手帮你进行了render,如果你自己render了,聪明的视图助手会知晓的,可以查看下在_shouldRender()中的这个 $this->getRequest()->isDispatched(),及Zend_Controller_Front 类中dispatch方法的这句话:$this->_request->setDispatched(true);

3.终极render 关于Zend_View->render()

好了现在我们来看看Zend_View的render().
在上面的两个中我们都说到了render(),比如action的render和视图助手的render
那么你该问个问题:就这样了?后面呢?
后面的才是关键的.
在action的render中,你可能注意到这句话了
10          $this -> getResponse() -> appendBody(
11              $view -> render( $script ) ,
12              $name
13         );
而我们再看看viewRenderer的render(),viewRenderer的render方法其实是调用了 renderScript 方法,代码如下
复制代码
 1      public   function  renderScript( $script ,   $name   =   null )
 2     {
 3          if  ( null   ===   $name ) {
 4              $name   =   $this -> getResponseSegment();
 5         }
 6
 7          $this -> getResponse() -> appendBody(
 8              $this -> view -> render( $script ) ,
 9              $name
10         );
11
12          $this -> setNoRender();
13     }
复制代码
可以看到这里跟action的render有点类似,也有同样的那句话.
就是说action的render和viewRenderer的render其实都是调用Zend_View的render,拿到内容而后置放到response中

Zend_View的render:
复制代码
 1      public   function  render( $name )
 2     {
 3          //  find the script file name using the parent private method
 4          $this -> _file  =   $this -> _script( $name );
 5          unset ( $name );  //  remove $name from local scope
 6
 7          ob_start ();
 8          $this -> _run( $this -> _file);
 9
10          return   $this -> _filter( ob_get_clean ());  //  filter output
11     }
复制代码

至于run:
复制代码
1      protected   function  _run()
2     {
3          if  ( $this -> _useViewStream  &&   $this -> useStreamWrapper()) {
4              include   ' zend.view:// '   .   func_get_arg ( 0 );
5         }  else  {
6              include   func_get_arg ( 0 );
7         }
8     }
复制代码

那么你就明白了最开始代码中的第13行
13         //$this->view->render("sidebar.phtml");
其实是个幌子,哈.这句话只是得到了内容,但是呢 没做处理!
所以我们应该这样
13         echo $this->view->render("sidebar.phtml");
再然后呢?参看Zend_Controller_Front类dispatch
 $this->_response->sendResponse();
及Zend_Controller_Response_Abstract类
1      public   function  outputBody()
2     {        
3          foreach  ( $this -> _body  as   $content ) {            
4              echo   $content ;
5         }
6     }


而至于第14行
14         //$this->view("sidebar"); 
貌似合理,瞪一眼就知道了:这句话地地道道的错误
action 中没有这个方法,__call中也没有相应处理,不象 _helper->viewRenderer("sidebar"); 在 _helper针对该情况在__call中有相应处理
复制代码
1      public   function  __call( $method ,   $args )
2     {
3          $helper   =   $this -> getHelper( $method );
4          if  ( ! method_exists ( $helper ,   ' direct ' )) {
5              require_once   ' Zend/Controller/Action/Exception.php ' ;
6              throw   new  Zend_Controller_Action_Exception( ' Helper " '   .   $method   .   ' " does not support overloading via direct() ' );
7         }
8          return   call_user_func_array ( array ( $helper ,   ' direct ' ) ,   $args );
9     }
复制代码
没有viewRenderer这个方法,于是去寻找名为viewRenderer并且有direct方法的助手,找到了即执行这个direct方法(上面第二部分贴过代码了)
至于viewRenderer这个助手存放时,要注意到他的名字是死的 就是"viewRenderer",具体看Zend_Controller_Action_Helper_Abstract类的getName方法
复制代码
 1      public   function  getName()
 2     {
 3          $full_class_name   =   get_class ( $this );
 4
 5          if  ( strpos ( $full_class_name ,   ' _ ' !==   false ) {
 6              $helper_name   =   strrchr ( $full_class_name ,   ' _ ' );
 7              return   ltrim ( $helper_name ,   ' _ ' );
 8         }  else  {
 9              return   $full_class_name ;
10         }
11     }
复制代码
之所以提到这点是因为在Zend_Controller_Action_Helper_ViewRenderer注释中你能看到这句话
// In your action controller methods:
$viewHelper = $this->_helper->getHelper('view');
而实际上你复制这句话到your action controller methods中去 只会出错

Exception information:

Message: Action Helper by name View not found 

个人感觉php Zend Framework还是很不错,虽然一直没搞好调试器
但是非常满意于可以随处置放var_dump

转载于:https://my.oschina.net/Xerxeschn/blog/82054

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值