Reputation: 13534
In CakeDC comments plugin for CakePHP documentation states that:
Component callbacks
It is possible to override or extend the most comments component methods in the controller. To do this we need to create method with prefix callback_comments Examples:
callback_add will named as callback_commentsAdd in controller, callback_fetchData will named as callback_commentsFetchData in controller. ...
It works from the controller perfectly!:
public function callback_commentsInitType() {
return 'flat'; // threaded, tree and flat supported }
I wonder, what is the new feature of cakephp-2.0 that allows you to do that? I need to understand how it was achieved to be able to implement such methodology in the future on my components.
Upvotes: 0
Views: 224
Reputation: 2060
In the code of the component, if you look at the following function in this file (starting from line number 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();
}
}
You can see that the variable $methodName
is being defined with prefix callback_comments
and then the passed $method
is appended to it after being treated by the Inflector::underscore
and then Inflector::camelize
method. The working of these is as follows:
Inflector::underscore
will convert initType
to init_type
. Check doc here.Inflector::camelize
will further convert init_type
to InitType
. Check doc here.Now, if initType
was passed in the argument, then the $methodName
will be:
callback_comments
+ InitType
= callback_commentsInitType
After this, a $localMethodName
is also being generated. In our initType
example, it will be:
callback_
+ initType
= callback_initType
After the names have been generated, it will simply search if the method exists in the attached controller and will execute it using call_user_func_array
function by passing it and array with the object (in our case, the controller object (&$this->Controller
) or the component object itself (&$this
)) containing the method and the $methodName
as first argument and then $args
as second argument.
If the function was not found in the controller, then it will instead search in the component with $localMethodName
. If it's found, then it is executed the same way.
Now how all this works is that the _call
function is the single function used to call all the internal functions of the component, so that it will first check if the function has been overwritten in the controller, otherwise it will execute the function in the component itself.
You can check the component's beforeRender function here and you'll see how the initType
function is called. In this case, if the controller contains a function named callback_commentsInitType
, then it will be executed. Otherwise, the components callback_initType
will be executed.
Hope this helps..
Upvotes: 2