【PHP】is_callable()與method_exists()函式
在很多產品應用中,我們經常能夠看到以下這種用法,它用來檢查一個物件裡的方法是否存在。
<?php
if (method_exists($object, 'SomeMethod')) {
$object->SomeMethod($this, TRUE);
}
?>
1
2
3
4
5
6
這段程式碼的目的比較容易理解,有一個物件為$object,我們想知道它是否有一個方法為SomeMethod,如果有,就呼叫此方法。
這個程式碼看起來正確,而且在大部分的時候執行也會正常。但是如果這個$object物件的方法對於當前的執行環境是不可見的,程式還能正常執行嗎?正如這個函式名方法存在一樣,只是對我們提供的類或物件檢查是否有我們所期望的方法,如果有,就返回TRUE,如果沒有,就返回FALSE,這裡並沒有考慮可見性的問題。所以,當你恰好判斷一個私有或者受保護的方法時,你能夠得到一個正確的返回,但是執行的時候,會得到一個“Fatal Error”錯誤警告。
上面這段程式碼的真正意圖應該理解為:對於提供的類或者物件,我們能否在當前的作用域中呼叫它的SomeMethod方法。而這正是is_callable()函式存在的目的。is_callable()函式接收一個回撥引數,可以指定一個函式名稱或者一個包含方法名和物件的陣列,如果在當前作用域中可以執行,就返回TRUE。
<?php
if (is_callable(array($object, 'SomeMethod'))) {
$object->SomeMethod($this, TRUE);
}?>
1
2
3
4
下面來舉個例子來說明兩者的區別
<?php
class Foo {
public function PublicMethod(){}
private function PrivateMethod(){}
public static function PublicStaticMethod(){}
private static function PrivateStaticMethod(){}
}
$foo = new Foo();
$callbacks = array(
array($foo, 'PublicMethod'),
array($foo, 'PrivateMethod'),
array($foo, 'PublicStaticMethod'),
array($foo, 'PrivateStaticMethod'),
array('Foo', 'PublicMethod'),
array('Foo', 'PrivateMethod'),
array('Foo', 'PublicStaticMethod'),
array('Foo', 'PrivateStaticMethod'),
);
foreach ($callbacks as $callback){
var_dump($callback);
var_dump(method_exists($callback[0], $callback[1]));
var_dump(is_callable($callback));
echo str_repeat('-', 10);
echo '<br />';
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
執行上面的指令碼後,我們會清晰地看到兩個函式間的差別。
is_callable()還有其他的用法,例如,不檢查所提供的類或方法,只檢查函式或方法的語法是否正確。像method_exists()一樣,is_callable()可以觸發類的自動載入。
如果一個物件存在魔術方法__call,在進行方法判斷時method_exists()會返回FALSE,而is_callable()會返回TRUE。
<?php
class MethodTest {
public function __call($name, $arguments){
echo 'Calling object method ' . $name . ' ' .implode(', ', $arguments);
echo '<br />';
}
}
$obj = new MethodTest();
$obj->runtest('in object context');
var_dump(method_exists($obj,'runtest'));
var_dump(is_callable(array($obj,'runtest')));
echo '<br />';
1
2
3
4
5
6
7
8
9
10
11
12
執行結果
Calling object method runtest in object context
bool(false) bool(true)
圖示
---------------------
https://blog.csdn.net/qq_28602957/article/details/65444356