PHPで関数・メソッドの存在を調べる関数

PHPで、ある関数が存在するかどうかを調べるためにはfunction_exists関数を使います。しかし、この関数ではメソッドの存在は調べることはできません。メソッドが存在するかどうかを調べるにはmethod_exists関数を使います。

文字列からその関数やメソッドが存在するか調べたいと思ったのですが、関数とメソッドを同じように調べたいという場合には、function_exists関数とmethod_exists関数を上手く使い分ける必要があります。PHPにありがちな、やりたいことは似ているけど関数は別々というやつですね :x

function_exits関数の使い方は、引数に文字列で関数名を渡すだけです。

if (function_exists('func')) {
    echo htmlspecialchars("func関数が利用可能です。\n", ENT_QUOTES, 'UTF-8');
} else {
    echo htmlspecialchars("func関数は利用できません。\n", ENT_QUOTES, 'UTF-8');
}

method_exists関数の場合は、オブジェクトかクラス名とメソッド名を渡します。

$instance = new Class();

if (method_exists($instance, 'method')) {
    echo htmlspecialchars("methodメソッドが利用可能です。\n", ENT_QUOTES, 'UTF-8');
} else {
    echo htmlspecialchars("methodメソッドは利用できません。\n", ENT_QUOTES, 'UTF-8');
}
if (method_exists('Class', 'method')) {
    echo htmlspecialchars("methodメソッドが利用可能です。\n", ENT_QUOTES, 'UTF-8');
} else {
    echo htmlspecialchars("methodメソッドは利用できません。\n", ENT_QUOTES, 'UTF-8');
}

さらに似たような関数で、「PHPの関数でコールバック関数を引数にする」で出てきた、関数として呼び出しが可能かどうかを調べるためのis_callable関数があります。引数は、「PHPでコールバック関数にオブジェクトのメソッドを指定する」で出てきたcallback擬似型で渡します。スピードは少し遅いみたいです。

callback擬似型や、関数名とクラスメソッド名のどちらの文字列が渡されても、その関数・メソッドが存在するかどうかを返すような関数を書いてみました。もっと簡単にできそうな気もしますが、似たような関数が多すぎて調べるのが大変なのでこんな感じにしときました。

function func_exists($func)
    if (false === $separator = strpos($func, '::')) {
        return is_array($func) ? method_exists($func[0], $func[1])
                                      : function_exists($func);
    } else {
        $class = substr($func, 0, $separator - 1);
        $method = substr($func, $separator + 2));
        return method_exists(array($class, $method));
    }
}

$func = 'func';
if (func_exists($func)) {
    echo htmlspecialchars("関数またはメソッドが利用可能です。\n", ENT_QUOTES, 'UTF-8');
} else {
    echo htmlspecialchars("関数またはメソッドは利用できません。\n", ENT_QUOTES, 'UTF-8');
}

$func = array('Class', 'method');
if (func_exists($func)) {
    echo htmlspecialchars("関数またはメソッドが利用可能です。\n", ENT_QUOTES, 'UTF-8');
} else {
    echo htmlspecialchars("関数またはメソッドは利用できません。\n", ENT_QUOTES, 'UTF-8');
}

$func = 'Class::method';
if (func_exists($func)) {
    echo htmlspecialchars("関数またはメソッドが利用可能です。\n", ENT_QUOTES, 'UTF-8');
} else {
    echo htmlspecialchars("関数またはメソッドは利用できません。\n", ENT_QUOTES, 'UTF-8');
}

PHPでは入れ子クラスはできるのでしょうか。できる場合には、スコープ定義演算子(::)の処理は変える必要がありますね。

'$instance->method'のようなインスタンスメソッドを表す文字列も、変数名とメソッド名を上手く分けるようにすれば処理できそうです。ただ、callback擬似型は多次元配列にはできないようなので(本当にできないのなら気持ち悪すぎます。)、'$instance1->$instance2->method'のようなものはarray_map関数を使うなりするように修正する必要があります。配列の場合とかも考えると面倒そうですね。

今回は、基本的には関数名とクラスメソッド名だけを処理できればよかったので、こんな感じの関数で解決できました。

コメント (2)

はじめまして、とても素晴らしい記事で、たまに参考にさせていただいております。

ところで、method_exists の説明のところですが、サンプルが function_exists になっているような気がします。

soraiさん、はじめまして。
ほんとですね…サンプルコードが間違えていたようです。修正しておきました!
ご指摘ありがとうございました。今後ともよろしくお願いします。

コメントフォーム

トラックバック (1)

[…] PHPで関数・メソッドの存在を調べる関数 – (DxD)∞ : http://dxd8.com/archives/84/ […]

この記事のトラックバックURI
http://dxd8.com/archives/84/trackback/
この記事のURI
http://dxd8.com/archives/84/