Respect/Rest

is_callable vs function/method_exists

Closed this issue · 5 comments

Busy fixing the tests after reintroducing the factory params needing an example that can take string, array as arguments I thought awesome ArrayObject will do the trick but lo and behold, for some weird and wonderful reason 'ArrayObject" 'offsetSet' is not callable, even though it works on the instance and method_exists sees it to be so. Strange?

var_export(method_exists('ArrayObject', 'offsetSet'));
// output: true
var_export(is_callable(array(new ArrayObject, 'offsetSet')));
// output: true
var_export(is_callable(array('ArrayObject', 'offsetSet')));
// output: false

Performance is also an issue as bob at thethirdshift dot net will tell you on PHP.net
Benchmark results:

Did 10000 is_callables in 0.0640790462494 seconds
Did 10000 function_exists in 0.0304429531097 seconds

We would have to do a combination of is_array, function_exist, method_exist; and then produce the benchmarks to see how it would affect us but if it fails in this example where else would it be mistaken?

+1 to method_exists.
is_callable fails :/

So sad this performance problem, btw if you run

call_user_func(array('ArrayObject', 'offsetSet'));

You will have the error

Warning: call_user_func() expects parameter 1 to be a valid callback, non-static method ArrayObject::offsetSet() cannot be called statically in Command line code on line 1

So method_exists will check if some method really exists in some object, but is really not a valid callback. What we need, a valid callback or check if a method exists in some object?

@nickl- ArrayObject->offsetSet is callable... from it's scope: an object, not a static method from a class. Passing array('ArrayObject', 'offsetSet') you're checking if offsetSet is callable statically. Having an instance, you can is_callable(array($arrayObjectInstance, 'offsetSet')) (or is_callable(array($arrayObjectInstance, 'ArrayObject::offsetSet')) for a private static method) and get appropriate results for it's correct scope.

@alganet Yes exactly, as per the results of:

var_export(is_callable(array(new ArrayObject, 'offsetSet')));
// output: true

I think the idea was to avoid is_callable due to performance but I don't recall that clearly, it kind of lost its context 5 months later.

I will try place it again and give feedback once recalled.

Nope still no clue, closing.