PHP __call 与 method_exists

Posted

技术标签:

【中文标题】PHP __call 与 method_exists【英文标题】:PHP __call vs method_exists 【发布时间】:2010-12-03 02:30:57 【问题描述】:

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

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

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

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

【问题讨论】:

好问题,我会玩这个。 需要的是另一种“神奇的方法” __canCall 什么的…… is_callable() 适用于类的实例。我根本不明白您为什么要使用 method_exists() 。 is_callable() 做了所有 method_exists() 做的事情,而且它与 __call() 一起工作。 【参考方案1】:

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

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

【讨论】:

似乎__call 没有“失败”的概念,所以看起来像在 __call 方法中抛出一个 NotImplementedException (或类似的)将是这样做的方法。【参考方案2】:

看看is_callable()

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

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

【讨论】:

is_callable() 如果定义了 __call() 会自动返回 true,使得 is_callable() 不可靠(因为它不能确保 __call() 满足请求)【参考方案3】:

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,也相当易读。

【讨论】:

【参考方案4】:

如果你真的确定 _call 总是有一个后备,你可以这样做:

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

【讨论】:

【参考方案5】:

我很想在你的 __call 函数中使用 method_existsthrowException 如果这失败并将所有内容包装在 try catch 块中,而不是使用 is_callable功能。

【讨论】:

以上是关于PHP __call 与 method_exists的主要内容,如果未能解决你的问题,请参考以下文章

PHP正向魔法方法

php中method_exists()和is_callable()如何进行语句判断

PHP中__call()方法与重载解析

PHP魔术方法之__call与__callStatic方法

php __CLASS__get_class()与get_called_class()的区别

php中__call() 和 __callStatic方法的使用