PHP: The Problem With is_callable() And __call()
So I ran into this problem with PHP: when you have a class that uses method overloading via __call(), is_callable() will always return true for any function given to it, no matter if it exists or not. I know this is by design, but it’s still heavily brain-damaged. Here’s an example of what I’m talking about:
class foo {
public function __call($name, $args)
{
echo "$name called\n";
}
}
$foo = new foo();
if (is_callable(array($foo, 'non_existent_method'))) {
echo "foo->non_existant_method() is callable\n";
}
My whole problem with this, is it’s completely undocumented. If you use method_exists(), you may expect it to return true for method overloading, but that’s not the case.
So:
is_callable() - Recognizes __call()
method_exists() - Doesn’t recognize __call()

April 22nd, 2009 at 7:15 pm
Yeah, I don’t think it’s explicitly documented, but it’s not a stretch to infer it:
“__call() is triggered when invoking inaccessible methods in an object context.”
“is_callable — Verify that the contents of a variable can be called as a function”
I don’t know whether it really qualifies as brain-damaged, but it could be more obvious.
The only way around it would be reflection and dynamic instances, so you could look at an object’s methods and replicate them in your object. This would solve it for a Decorator implementation, but I’m sure there are usecases where it’s less optimal.
PHP really isn’t flexible enough to support a fully dynamic programming model like that, though.
April 22nd, 2009 at 9:10 pm
The documentation should really clarify this. Assuming you can tell by looking at the function name is stupid. There’s a lot of little things like this in PHP, that drive me crazy.
April 22nd, 2009 at 10:11 pm
Not sure I follow you. Assuming you can tell what by looking at the function name?
April 23rd, 2009 at 12:20 pm
Ugh. Sorry. I should probably stop posting comments when I’m tired.
Yeah, you might be able to infer the behavior of is_callable() from the documentation, but thats an assumption. In some places, the documentation doesn’t give a good enough description of how things function under certain situations. I’ve ran into this a couple times before.