PHP __call vs method_exists

时间:2009-10-01 18:37:44

标签: php overloading

我正在处理的项目包含类似call_user_func(_array)的包装器,它在执行之前执行一些检查。 其中一个检查是method_exists(In Case,提供的第一个参数是类的实例,第二个参数是方法名称) 另一个是__ callable。 如果其中一个检查失败,该函数将抛出异常。

我的代码包含一个带有函数名称的数组(setFoo,setBar等)和用于重载(__call)的php magic函数,它处理某些变量的设置,替换和删除(更好的某些数组元素)。

问题: 如果未定义函数,method_exists将返回false。

如果__call函数正确处理请求,我是否有机会获得真假?

5 个答案:

答案 0 :(得分:8)

__call处理对不存在的方法的调用。 method_exists是一种内省方法,用于检查方法的存在。

如何确定__call处理方法?我认为如果不处理您的请求,则必须在__call中手动抛出异常,并在代码中捕获异常,否则将使用method_exists。为此目的存在BadMethodCallException

答案 1 :(得分:5)

查看is_callable()

但不,如果__call()方法只处理某些名称,那么你需要一些其他方法来检查调用是否会成功。

我可以建议使用方法canCall($function)的接口,还是什么?然后检查类是否实现了接口。如果没有,请使用is_callable()

答案 2 :(得分:4)

method_exists尝试两件事:

  • 在类的函数表中搜索方法名称。这些是function foo() {}类型的方法。
  • 检查类(C代码)是否具有(C代码)get_method()函数,以及它是否已调用它以让类实现决定。

你需要后者。但是这个get_method()没有“扩展”到php脚本代码,即没有办法让get_method()调用一些用户定义的php脚本代码(这个php代码会返回什么?)。

所以我最了解的答案是:不,这是不可能的(但是?)。

ZEND_FUNCTION(method_exists)的实现可以在zend/zend_builtin_functions.c中找到,即使您不了解C而且PHP也是如此,我认为它是相当可读的。

答案 3 :(得分:1)

我很想在method_exists函数中使用__callthrow Exception如果失败并将所有内容包装在try {{} {1}}阻止而不是使用catch函数。

答案 4 :(得分:1)

如果你确定_call总是有回落,你可以这样做:

if (method_exists($this, $method_name) || method_exists($this, '__call')) {
  // Call of the method
}