作者:老王
CakePHP的
控制器结构中,CakePHP核心有一个Controller“爷类”控制器,我们可以自
定义的有一个AppController“父类”控制器,然后我们自定义的“子类”控制器都从它继承。这样,我们就可以在AppController父控制器或者自定义的子控制器里初始化helpers和components属性。早在CakePHP1.1.X的时候,如果我们在自定义的子控制器中设置了helpers和components,会覆盖AppController父控制器中的对应设置,这样会造成很多不方便。还好,在CakePHP1.2.X中,各个控制器中的helpers及components会自动合并,而不是覆盖。但是,如果你不熟悉的话,有时候会出现很诡异的情况,下面,我给一个简单的介绍:
以下代码环境均以假定在CakePHP1.2.0.5427alpha版本进行。
首先,我们在app目录建立自定义的app_controllers.php文件:
复制内容到剪贴板
代码:
class AppController extends Controller
{
// 暂时不设定 var $helpers 和 var $components
}
再在app/controllers目录下建立自定义的demo_controllers.php文件:
class DemoController extends Controller
{
// 暂时不设定 var $helpers 和 var $components
function index()
{
pr($this->helpers);
pr($this->components);
exit;
}
}这时,我们浏览一下demo,就会看到CakePHP的缺省helpers和components分别是:
复制内容到剪贴板
代码:
helpers: Html
components: Session在
源代码里,我们能找到这些缺省设置的相关代码:
在controller.php文件里可以看到 var $helpers = array('Html'); 设置,所以不难理解helpers的缺省设置,但是同样在controller.php文件里也可以看到 var $components = array(); 设置,那么为啥最后会出现Session呢?原来这个Session组件的设置是在component.php文件里设置的:
复制内容到剪贴板
代码:
$this->controller->components = array_merge($this->controller->components, array('Session'));知道了helpers和components最基本的缺省设置之后,我们来尝试改变一下,在DemoController里加入下面的定义:
复制内容到剪贴板
代码:
var $helpers = array('Javascript');
var $components = array('Email');浏览一下demo,就会看到CakePHP的缺省helpers和components分别是:
复制内容到剪贴板
代码:
helpers: Javascript,Html
components: Email,Session不错,没有覆盖掉父类的设置,都按预想进行。那么我们再尝试改变一下,在AppController里加入下面的定义:
复制内容到剪贴板
代码:
var $helpers = array('Form');
var $components = array('Security');浏览一下demo,就会看到CakePHP的缺省helpers和components分别是:
复制内容到剪贴板
代码:
helpers: Javascript,Form
components: Email,Security,Session看到这里,可能会感觉比较诡异,Html助手不见了,而Session组件还在。至于为啥会这样,我们可以在controller.php文件里找到相关的代码:
复制内容到剪贴板
代码:
if (is_subclass_of($this, 'AppController')) {
$appVars = get_class_vars('AppController');
...
$merge = array('components', 'helpers');
...
foreach ($merge as $var) {
if (isset($appVars[$var]) && !empty($appVars[$var]) && is_array($this->{$var})) {
$this->{$var} = array_merge($this->{$var}, array_diff($appVars[$var], $this->{$var}));
}
}
}从array_merge($this->{$var}, array_diff($appVars[$var], $this->{$var}));中可以看出,在这部分设定中,排除了可能的重复。既然说到重复的问题,我们回过头看看上面对于Session的处理代码:
$this->controller->components = array_merge($this->controller->components, array('Session'));
可以看出这里没有排除可能的重复。
如果没看懂也没有什么关系,只要记住下面的结论性提示就可以了:如果不想被helpers和components的初始化搞蒙,那么在建立自定义的AppController的时候,一定要在helpers里把Html重新设定一次,但是,不管是在AppController里,还是你自定义的子控制里,都不要设定Session组件,不然就会出现重复。
这也说明了CakePHP代码目前还存在很多不严谨的地方,在1.2Stable的时候,应该会好起来。