博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
明晰php Zend Framework中的render
阅读量:7045 次
发布时间:2019-06-28

本文共 5783 字,大约阅读时间需要 19 分钟。

hot3.png

搞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

你可能感兴趣的文章
Leetcode 16. 3Sum Closest
查看>>
linux及git记录
查看>>
自制jq分页插件
查看>>
详解js变量声明提升
查看>>
【windows】win10正式版分享WiFi热点
查看>>
程序与文档
查看>>
独孤九剑(0x04) - 测试篇
查看>>
JS学习总结
查看>>
一个前端写的php博客系统--支持markdown哦
查看>>
Laravel Taggable 为你的模型添加打标签功能
查看>>
Erlang/Elixir: 使用 Edeliver 进行自动化的持续部署
查看>>
Nodejs检测端口是否被占用
查看>>
webpack入坑之旅(二)loader入门
查看>>
如何优雅高效地插入百度广告
查看>>
DbUtils应用在Android6.0中为什么会崩溃
查看>>
OpenJDK9 Hotspot Mac OSX 编译和调试
查看>>
守护进程, 孤儿进程, 僵尸进程与waitpid
查看>>
Django 安全策略的 7 条总结!
查看>>
Android:我为何要封装DialogFragment?
查看>>
表单知识总结
查看>>