此时,前端控制器已经实例化一个页面控制器,并且调用了它的fetch()方法。现在,页面控制器查看URI的剩余部分,初始化自己,对URI做相关的处理,然后把处理的结果交付给一个响应对象。当这一切都结束的时候,它把那个响应对象返回给前端控制器。
页面控制器是调度过程中最复杂的部分,操作上有3个不同的阶段:
-
初始化和加载
-
执行动作
-
渲染结果
构造函数__construct()最后一条命令是调用_setup() 方法;你可以在_setup()函数中放置个性化的初始化代码。这些初始化代码在加载页面控制器和接收URI信息之前执行。
当前端控制器调用页面控制器的fetch()方法时,前端控制器把当前请求的URI的剩余部分传给页面控制器(前端控制器已经去除URI的第一个路径信息元素,因为它已经被用于决定实例化哪个页面控制器)。fetch()方法做的第一件事是根据URI加载页面控制器对象的属性。
$_controller
-
这是从URI中获得的页面控制器的名字。页面控制器的名字是在其被实例化的时候由前控制器设置的。例如:URI 路径 /blog/read/123/foo 将会在页面控制器
Vendor_App_Blog
中设置$_controller = 'blog'
。 $_action
-
URI的剩余部分(前端控制器中已经去除页面控制器名字)的第一个元素。例如,URI路径
/blog/read/123/foo
将设置$_action = 'read'
。这些被转化为页面控制器调用actionRead()
方法。 $_info
-
action之后URI中剩余的路径信息元素。例如,URI路径
/blog/read/123/foo
将会设置$_info = array('123', 'foo')
。这些参数将通过call_user_func_array()
函数传递给action方法,因此,你不需要直接访问它们。 $_format
-
它的值是URI的最后一个路径信息元素-格式扩展名,当且令当action方法能够识别这种格式。如果这种格式不能被识别,那么它会被加到
$_info
数组的最后一部分(你可以通过$_action_format
数组设置可识别的某些特殊的格式扩展名,数组的键是action方法名字,数组的值是可被识别的格式扩展名的数组)。例如,假设URI为
/blog/read/123/foo.rss
。如果有$_action_format['read'] = array('rss')
,那么actionRead()
方法将能够识别rss
请求,并且你会得到$_format = 'rss'
。但是如果$_action_format
中没有那条记录,$_format
将为空,并且actionRead()
方法的参数不再是('123', 'foo')
,而是('123', 'foo.rss')
。 $_layout
-
这个属性指定在两步视图过程的布局模板的名字。当
$_format
非空时,$_layout
将被自动设为空。这就表明,正在请求的是非标准格式,如XML或RSS;这些非标准格式的请求通常是不需要页布局的。 $_query
-
这是由输入URI的查询项和值构成的数组。例如,查询字符串
?foo=bar&baz=dib
将会变成$_query = array('foo' => 'bar', 'baz' => 'dib')
。
这里简单介绍一下执行请求的动作时发生的事情:
-
调用
_preRun()
方法,在此方法中可以改变上面初始化后的某些属性。 -
执行
_preAction()
hook。(下一步,当前动作可能会调用_forward()
方法路转至其他动作,所以每次跳转发生时,这个hook都会执行) -
执行动作方法本身,使用
$_action
属性决定执行哪个动作,并使用储存在$_info
属性中的URI参数。(这部分是动作的逻辑中心,是由开发者完成的。)例如,给定URI “/blog/read/123/foo” ,系统最终会调用Vendor_App_Blog::actionRead('123', 'foo')
。 -
执行
_postAction()
hook。(上一步,动作可能已经调用_forward()
方法跳转至其他动作,所以每次跳转发生时,这个hook都会执行) -
最后,调用
_postRun()
方法,此方法可能会改变由动作处理过的属性的结果。
这里简单介绍下渲染请求动作的结果时发生的事情:
-
_setViewObject()
方法为渲染过程初始化一个Solar_View对象。为了实现这一步,该方法给视图添加模板路径栈,给视图辅助类添加类前缀栈。它还向视图中注入一些特殊的变量,如下:$controller_class
、$controller
、$action
、$layout
、$format
和$errors
。 -
在视图对象初始化之后,渲染过程调用
_preRender
方法。这样的话,在渲染发生之前,你仍可以修改视图对象或页面控制器的属性。 -
页面控制器把其所有的公共属性传递给视图对象,因此这些公共属性在模板中可用。
-
如果已经为属性
$_view
设置了模板名,页面控制器调用视图对象的fetch()方法时,将使用这个模板名。处理完模板后,就返回它的输出。输出被放置在页面控制器的$_response->content
属性中。(这是两步视图的第一步)Note 默认情况下,
$_view
属性的值和action方法名是相同的;例如,如果action名为“actionFooBar”,那么$_view
的值就为“fooBar”。这也意味着模板文件名为fooBar.php
。如果指定了一个可识别的格式,那么指定的格式扩展会出现在
.php
之前。例如,如果$_format = 'rss'
,渲染过程会查找名为fooBar.rss.php
的模板文件。这也就是说,你可以用同一个action方法,同样的数据产生不同的视图响应。 -
在视图被渲染之后,如果为
$_layout
属性设置了布局模板名,页面控制器将重用视图对象(包含它所有的变量和辅助方法/类)渲染布局模板。这是通过设置模板路径栈为布局模板并把已存在的$_response->content
属性值放置布局模板的适当位置来完成的。这个结果将覆盖$_response->content
属性的值,这也是两步视图的第二步。 -
渲染过程现在基于
$_format
属性的值和$_format_type
数组的映射设置$_response
对象的内容类型。 -
最后,渲染过程调用
_postRender()
方法,这样就能够让开发者按需修改$_response
对象的内容了。