Use is_callable() instead of method_exists() in canGetProperty(),etc. methods of CComponent

method_exists() does not care about the existence of __call(), whereas is_callable() does.

So if we will replace method_exists() to is_callable(), it will give much more flexibility.

For example you will able to create behaviors which magic methods (__call(), __get(), __set()) will be applied to owner too. Or even create behaviors for behaviors :)

I encountered with this problem, when tried to create multilangual AR behavior and versionable AR behavior (CVS) that saves data in "<ownerTableName>_revisions" and "<ownerTableName>_translations" tables.

I suppose you must post this to the http://code.google.com/p/yii/ page

Here is more space to discuss it and decide: Is this feature needed?

Coz if I will post it only to code.google issues, Qiang can say something like “That goes too far…” :)

What about performace of these methods?

I guess that method_exists() faster, but we need to test it.

Also if replace method_exists() to is_callable() in CController::createAction, we will able to specify additional actions for controller via behaviors.

I made some tests and found, that is_callable() is faster than method_exists():

method_exists time:7.47126793861

is_callable time:6.26710391045




<?php 

$directory = new Directory('.');


$start_time = explode(" ", microtime());

$start_time = $start_time[1] + $start_time[0];




for ($i=1;$i<10000000;$i++)

	method_exists($directory,'read');


$end_time = explode(" ", microtime());

$end_time = $end_time[1] + $end_time[0];

echo '<br>method_exists time:' . ($end_time - $start_time);




$start_time = explode(" ", microtime());

$start_time = $start_time[1] + $start_time[0];


$params = array($directory,'read'); 

for ($i=1;$i<10000000;$i++)

	is_callable(&$params);


$end_time = explode(" ", microtime());

$end_time = $end_time[1] + $end_time[0];

echo '<br>is_callable time:' . ($end_time - $start_time);



Also, method_exists() vs is_callable()

(russian translation)

So to be sure for all situations… the best usage would be…


 

if method_exist(…) && is_callable(…)

   make the call



mdomba, using of method_exist(…) && is_callable(…) will nullify all advantage of using is_callable(…), this function is self-sufficient in case of using that I propose.

but as the article you pointed above say:

in this case… the call will be made to the non-existing method again an error would be generated…

Oh, I see, I read it inattentively.

Сonsidering this I propose to add methodExists(‘name’) method to CComponent and use it.

In simple cases it will just run method_exists (or check behaviors/etc in addition).

Then in child classes we can redefine it to consider methods, implemented via __call