PHP Conference Japan 2024

method_exists

(PHP 4, PHP 5, PHP 7, PHP 8)

method_exists檢查類別方法是否存在

描述

method_exists(object|string $object_or_class, string $method): bool

檢查給定的 object_or_class 中是否存在類別方法。

參數

object_or_class

物件實例或類別名稱

method

方法名稱

傳回值

如果由 method 給定的方法已針對給定的 object_or_class 定義,則傳回 true,否則傳回 false

範例

範例 #1 method_exists() 範例

<?php
$directory
= new Directory('.');
var_dump(method_exists($directory,'read'));
?>

以上範例會輸出

bool(true)

範例 #2 靜態 method_exists() 範例

<?php
var_dump
(method_exists('Directory','read'));
?>

以上範例會輸出

bool(true)

備註

備註:

如果類別還未知,使用此函式將會使用任何已註冊的 自動載入器

參見

新增註解

使用者貢獻的註解 20 則註解

65
phoenix at todofixthis dot com
13 年前
如 [其他地方] 所述,method_exists() 不在意 __call() 的存在,而 is_callable() 在意

<?php
class Test {
public function
explicit( ) {
// ...
}

public function
__call( $meth, $args ) {
// ...
}
}

$Tester = new Test();

var_export(method_exists($Tester, 'anything')); // false
var_export(is_callable(array($Tester, 'anything'))); // true
?>
29
El
5 年前
自 7.4.0 發布以來,未記錄的變更

<?php
class Foo
{
private function
privateMethodTest()
{

}
}

class
Bar extends Foo
{

}

var_dump(method_exists(Bar::class, 'privateMethodTest'));
// PHP 7.4: bool(false)
// PHP 7.3: bool(true)

var_dump(is_callable(Bar::class, 'privateMethodTest'));
// PHP 7.3: bool(true)
// PHP 7.4: bool(true)
19
jave [at] issomewhereontheweb [com]
8 年前
此函式不在意類別是否存在,因此您可以使用它來檢查方法是否存在,即使類別未宣告,例如
<?php
if( method_exists('THIS_WAS_NOT_DECLARED', 'some_method') )
echo
"它確實存在!";
else
echo
"不,它不在那裡...";
?>
...不會引發任何錯誤/警告...如果類別根本不存在,或如果類別存在但方法不存在,則輸出「不,它不在那裡...」。
21
w3dk
9 年前
一些較舊的註解(特別是「jp at function dot fi」和「spam at majiclab dot com」)指出,當在該類別外部檢查時,is_callable() 不會考慮方法的可见性。也就是說,當公開測試時,私有/受保護的方法會被視為可呼叫。但是,這是 PHP 5 早期版本中的錯誤 (#29210),並且已在 PHP 5.0.5(和/或 PHP 5.1.0)中修復(根據變更日誌)。

Bug #29210 - Function: is_callable - no support for private and protected classes
http://bugs.php.net/29210

變更日誌 - 修復錯誤 #29210(Function: is_callable - 不支援私有和受保護的類別)。 (Dmitry)
https://php.dev.org.tw/ChangeLog-5.php#5.1.0
22
benjamin_ansbach at web dot de
21 年前
如果您想要檢查類別「內部」的方法,請使用

method_exists($this, 'function_name')

我有點困惑,因為我認為我只能在得到一個物件時才能檢查方法,例如 $object_name = new class_name(),使用

method_exists($object_name, 'method_name')

給那些不明白我意思的人的一個小範例(也許是因為我的英文不好 :))

<?php

class a {

function
a() {

if(
method_exists($this, 'test'))
echo
'a::test() 存在!';
else
echo
'a::test() 不存在';

}


function
test() {

return
true;

}

}

$b = new a();

?>

輸出將為:a::test() 存在!

也許這會對某些人有幫助
17
florin from syneto net
15 年前
此函式不區分大小寫(與 PHP 一樣),以下是證明
<?php
class A {
public function
FUNC() { echo '*****'; }
}

$a = new A();
$a->func(); // *****
var_dump(method_exists($a, 'func')); // bool(true)
?>
21
Niels
13 年前
只是提一下:method_exists() 和 is_callable() 都會對繼承的方法傳回 true

<?php
class ParentClass {

function
doParent() { }
}

class
ChildClass extends ParentClass { }

$p = new ParentClass();
$c = new ChildClass();

// all return true
var_dump(method_exists($p, 'doParent'));
var_dump(method_exists($c, 'doParent'));

var_dump(is_callable(array($p, 'doParent')));
var_dump(is_callable(array($c, 'doParent')));
?>
9
konzertheld at thedomainistheusersname dot de
11 年前
請注意,即使呼叫的類別在相同的命名空間中,也需要加上命名空間(如果有的話)。

<?php
namespace test;
class
foo {
public function
lookup() {
// 將會回傳 false
return method_exists('bar', 'nonsense_method');
}
}

class
bar {
public function
nonsense_method() {
// 將會回傳 true
return method_exists('test\foo', 'lookup');
}
}
?>
6
Anonymous
14 年前
如果您想在類別本身中檢查是否知道某個方法,您可以使用魔術變數 __CLASS__ 來實現。

<?php

class A{
__construct($method){
return
method_exists(__CLASS__,$method);
}

private function
foo(){

}
}

$test = new A('foo');
//應該回傳 true

?>

您也可以使用下方描述的方法搭配 <?php in_array() ?> 技巧,但我認為這裡的這個方法更容易理解、更具可讀性,而且是應該使用的方式;)
4
daniel at softel dot jp
18 年前
請注意,在 PHP5 中,method_exists() 將會成功找到 *private* 方法。這會產生一些關於物件導向/資料隱藏的影響。
1
uramihsayibok, gmail, com
14 年前
雖然沒有明確說明,但可以推斷出:method_exists() 也適用於介面。

<?php

var_dump
(method_exists("Iterator", "current"));
// bool(true)

?>
2
jpgiot at nospam ifrance.com
20 年前
一點小差異

尋找物件的方法(類別的實例)

<?php
if (method_exists($myinstance,'themethod'))
echo
'ok';
?>

尋找類別的方法(使用類別名稱,而不是類別的實例!)

<?php
if (is_callable(array('theclassname','themethod')))
echo
'ok';
?>
-1
admin ( at ) djokodonev dot com
15 年前
嗨,

這是一個有用的函式,可用於檢查類別方法的存取權限,例如它是 public、private 或 static,或者兩者都是。

以下是程式碼

<?php
// 範例類別
class myClass {

private
$private1;

static
$static1;

public
$public1;


public function
publ() {

}

private function
priv() {

}

private static function
privstatic() {

}

public static function
publstatic() {

}

static function
mytest() {

}
}

// 這個函式使用 PHP 內建的反射類別!!!
// 目的是判斷某個存在的方法的類型
function is_class_method($type="public", $method, $class) {
// $type = mb_strtolower($type);
$refl = new ReflectionMethod($class, $method);
switch(
$type) {
case
"static":
return
$refl->isStatic();
break;
case
"public":
return
$refl->isPublic();
break;
case
"private":
return
$refl->isPrivate();
break;
}
}
var_dump(is_class_method("static", "privstatic", "myClass")); // true - 這個方法是 private 而且也是 static
var_dump(is_class_method("private", "privstatic", "myClass")); // true - 這個方法是 private 而且也是 static
var_dump(is_class_method("private", "publstatic", "myClass")); // False - 這個方法是 public 而且也是 static,不是 private
// 你應該明白了.. 希望這對某些人有幫助..
?>
-3
charleston olaes at gmail no spaces
10 年前
我一直在想,將方法緩存在陣列中是否會更快。所以我使用 xdebug_time_index() 進行了一個非常簡單的基準測試,每個語句執行 10000 次迭代。

順帶一提,我使用的是 PHP 5.3.13

<?php
// 使用物件的實際實例顯示 0.10398316383362 秒
method_exist($object, $method);
?>

<?php
// 使用字串顯示 0.12779307365417 秒
method_exist('ClassName', $method);
?>

<?php
$array
= array(/*具有數字索引的方法名稱*/);
// 顯示 0.10288906097412 秒
in_array($method, $array);
?>

<?php
$assoc
= array( /*方法名稱作為鍵和值*/ );
// 顯示 0.017536878585815 秒
isset( $assoc[$method] );
?>

從結果來看,method_exist 和 in_array 的差異非常小。isset 似乎是最快的,而使用字串作為第一個參數是最慢的。

請注意,這個測試是在多個方法上進行的,而不只是一個,上面呈現的程式碼是為了顯示結果,而不是實際執行的測試程式碼。此外,這項測試只是出於好奇而進行的,我沒有設定特定的環境或使用任何效能分析工具,它並不是任何形式的正式基準測試。
-2
j dot metzger at steptown dot com
22 年前
call_user_method 使用與正常方法呼叫相同的機制。因此,您也可以透過這種方式取得回傳值。

$pagetext=call_user_method($method,$object_call);

所有資訊都會在 $pagetext 中。
-5
jp at function dot fi
18 年前
如同之前所述,`is_callable` 和 `method_exists` 會回報所有可呼叫的方法,即使它們是私有 (private) 或受保護 (protected) 的,因此實際上無法呼叫。所以,您可以使用以下變通方法來取代這些函式,它會回報預期的方法。

<?php
class Foo1 {
public function
bar() {
echo
"I'm private Foo1::bar()";
}
}

class
Foo2 {
private function
bar() {
echo
"I'm public Foo2::bar()";
}
}

$f1=new Foo1;
$f2=new Foo2;

if(
is_callable(array($f1,"bar"))) {
echo
"Foo1::bar() is callable";
} else {
echo
"Foo1::bar() isn't callable";
}
if(
is_callable(array($f2,"bar"))) {
echo
"Foo2::bar() is callable";
} else {
echo
"Foo2::bar() isn't callable";
}
if(
in_array("bar",get_class_methods($f1))) {
echo
"Foo1::bar() is callable";
} else {
echo
"Foo1::bar() isn't callable";
}
if(
in_array("bar",get_class_methods($f2))) {
echo
"Foo2::bar() is callable";
} else {
echo
"Foo2::bar() isn't callable";
}

?>

輸出
Foo1::bar() is callable (正確)
Foo2::bar() is callable (不正確)
Foo1::bar() is callable (正確)
Foo2::bar() isn't callable (正確)

?>
-5
mail at bartrail dot de
13 年前
如果在物件的 `__call()` 方法中使用 `method_exists`,當您想要避免因為函式巢狀限制而導致嚴重錯誤,或者當您呼叫不存在的方法但需要在應用程式中繼續時,會非常有用。

<?php
class Something
{

/**
* 動態呼叫方法
*
* @param string $method
* @param array $args
* @return mixed
*/
public function __call($method, $args)
{
if(
method_exists($this, $method)) {
return
call_user_func_array(array($this, $method), $args);
}else{
throw new
Exception(sprintf('The required method "%s" does not exist for %s', $method, get_class($this)));
}
}

}
?>
-3
spam at majiclab dot com
18 年前
`method_exists()` 和 `is_callable()` 都會回傳私有和受保護的函式,如同下面提到的,這會對 PHP5/OO 程式設計造成問題。您可以使用 `get_class_methods()` 搭配類別的 `$instance` 或 'ClassName' 來僅取得公開的函式。
-2
Thomas@ThBeckmann
21 年前
雖然如同 Benjamin 指出的,在類別定義內無法在 `method_exists` 中使用類別名稱,但 `get_class_methods` 即使在類別內部也會為給定的類別名稱提供方法名稱。因此,針對上述問題的另一種變通方法是使用 `in_array(<method_name>, get_class_methods(<class_name>))`。
-5
@prhldchauhan
2 年前
如果您想在包含這個類別後,在不同的檔案中使用 "method_exit" 函式,那麼您不能直接使用 "method_exit"。

因此,您必須對類別中已有的基本函式使用 `call_user_func_array`。

然後以下列方式呼叫函式 =>

function check($fun) {

if(method_exists($this, $fun))
{return true;}
else
{return false;}


}
To Top