在组件的代码中,如果你看this文件中的以下函数(从第622行开始):
/**
* Call action from commponent or overriden action from controller.
*
* @param string $method
* @param array $args
* @return mixed
*/
protected function _call($method, $args = array()) {
$methodName = 'callback_comments' . Inflector::camelize(Inflector::underscore($method));
$localMethodName = 'callback_' . $method;
if (method_exists($this->Controller, $methodName)) {
return call_user_func_array(array(&$this->Controller, $methodName), $args);
} elseif (method_exists($this, $localMethodName)) {
return call_user_func_array(array(&$this, $localMethodName), $args);
} else {
throw new BadMethodCallException();
}
}
您可以看到变量$methodName 是用前缀callback_comments 定义的,然后在经过Inflector::underscore 和Inflector::camelize 方法处理后,将传递的$method 附加到它上面。它们的工作如下:
-
Inflector::underscore 会将initType 转换为init_type。检查文档here。
-
Inflector::camelize 将进一步将init_type 转换为InitType。检查文档here。
现在,如果在参数中传递了initType,那么$methodName 将是:
callback_comments + InitType = callback_commentsInitType
在此之后,还会生成一个$localMethodName。在我们的initType 示例中,它将是:
callback_ + initType = callback_initType
生成名称后,它会简单地搜索该方法是否存在于附加的控制器中,并使用call_user_func_array 函数执行它,方法是将对象和数组传递给对象(在我们的例子中,控制器对象(@987654348 @) 或包含方法的组件对象本身 (&$this)) 和 $methodName 作为第一个参数,然后 $args 作为第二个参数。
如果在控制器中没有找到该函数,那么它将改为在带有$localMethodName 的组件中搜索。如果找到,则以同样的方式执行。
现在这一切的工作原理是_call函数是用于调用组件所有内部函数的单个函数,因此它会首先检查该函数是否已在控制器中被覆盖,否则将执行组件本身的函数。
您可以查看组件的 beforeRender 函数here,您将看到initType 函数是如何被调用的。在这种情况下,如果控制器包含一个名为callback_commentsInitType 的函数,那么它将被执行。否则,将执行组件callback_initType。
希望这会有所帮助..