is_callable() のススメ
PHP で、クラスに関数が定義されている場合のみ当該関数を call する〜なんてことをする際に、下記のようなコードを書いていたのですが、、、
<?php if (method_exists($hoge, 'func')) { $hoge->func(); }
「これって、func() が存在するけどその scope から呼べないケースどうなるん?private 関数とか。」という声を聞いて、これはまずそうだなと。
こんなとき、is_callable() ってのを使うと良いみたい。
PHP: is_callable - Manual
以下、サンプルコード。
<?php class Hoge { public function this_is_public() {} protected function this_is_protected() {} private function this_is_private() {} } $hoge = new Hoge(); if (method_exists($hoge, 'this_is_public')) { echo 'aaa' . PHP_EOL; } if (method_exists($hoge, 'this_is_protected')) { echo 'bbb' . PHP_EOL; } if (method_exists($hoge, 'this_is_private')) { echo 'ccc' . PHP_EOL; } if (is_callable(array($hoge, 'this_is_public'))) { echo 'ddd' . PHP_EOL; } if (is_callable(array($hoge, 'this_is_protected'))) { echo 'eee' . PHP_EOL; } if (is_callable(array($hoge, 'this_is_private'))) { echo 'fff' . PHP_EOL; } $hoge->this_is_public(); //$hoge->this_is_protected(); // Fatal error: Call to protected method Hoge::this_is_protected() from context '' in ... //$hoge->this_is_private(); // Fatal error: Call to private method Hoge::this_is_private() from context '' in ...
$ php ./test.php aaa bbb ccc ddd
method_exists() はアクセス指定が何であろうと、関数さえ定義されてれば true 判定。
is_callable() はアクセス可能な場合のみ、true 判定。
冒頭のケースでは、明らかに後者のが適切ですね。。。
試しに上のクラスを継承したら protected な関数も is_callable() = true と判定されました。
<?php class Hoge { ... } class Fuga extends Hoge { public function test() { if (is_callable(array($this, 'this_is_public'))) { echo 'ddd' . PHP_EOL; } if (is_callable(array($this, 'this_is_protected'))) { echo 'eee' . PHP_EOL; } if (is_callable(array($this, 'this_is_private'))) { echo 'fff' . PHP_EOL; } } } $fuga = new Fuga(); $fuga->test();
$ php ./test.php aaa bbb ccc ddd ddd eee