Callable
PHPの要素で関数として呼び出すことができるものをコールバックまたは callable といいます。
参考:PHP: コールバック / Callable - Manual
本記事のタイトルにもあるとおり、コールバック関数といわれることもあるようです(実際 PHP マニュアルにも書かれています)。
無用な混乱をさけるため、本記事では呼び方を callable で統一することにします。
Examples
説明を読んだだけでは理解できないと思いますので、callable の例をたくさんみていくことにしましょう。
例1
function hello() {
echo 'こんにちは。';
}
echo is_callable('hello') . PHP_EOL;
call_user_func('hello');
1
こんにちは。
5行目のis_callable
は、引数が callable であるかどうかを調べてくれる関数です。
is_callable
— 引数が、関数としてコール可能な構造であるかどうかを調べる
引数が callable ならtrue
を、 そうでなければfalse
を返します。
また、echo true
は1
を出力しecho false
は何も出力しません。
上記の例では1
が出力されていますので、is_callble
の引数である文字列hello
は callable であることがわかりました。
callable であるということは、文字列hello
を関数として呼び出せるということです。
実際に、7行目でcall_user_func
という関数をつかって callable である文字列hello
を関数として呼び出しています。
call_user_func
— 最初の引数で指定したコールバック関数をコールする
こんにちは。
と出力されていますので、1〜3行目で定義されている関数hello
が呼び出されたことがわかりますね。
一般に、関数foo
が定義されているとき文字列foo
は callable となります。
このとき文字列foo
をcall_user_func
にわたすことによって、関数foo
を呼び出すことができます。
例2
function hello() {
echo 'こんにちは。';
}
echo is_callable(hello) . PHP_EOL;
call_user_func(hello);
PHP Warning: Use of undefined constant hello - assumed 'hello' (this will throw an Error in a future version of PHP) in ...
PHP Warning: Use of undefined constant hello - assumed 'hello' (this will throw an Error in a future version of PHP) in ...
今回はエラーが出てしまいました。
エラーメッセージをよく読むとUse of undefined constant hello - assumed 'hello'
と書かれています。
これは「定義されていない定数hello
をつかっているようだけど、それは文字列hello
のことじゃないか?」という意味です。
例1の5行目と7行目では、hello
を二つのシングルクォーテーション(''
)でかこむことによって、それが文字列であることを表していました。
今回の例では、シングルクォーテーションでかこむことをしなかったため、hello
は定数として解釈されます。
このとき PHP は定数hello
の値を関数にわたそうとします。
ところが定数hello
は定義されていませんので、PHP はたいへん狼狽し、エラーメッセージを吐き、森へ帰ってしまったというわけです(?)。
PHP 関数はその名前を単に文字列として渡します。
例3
function sum($int1, $int2) {
return $int1 + $int2;
}
echo is_callable('sum') . PHP_EOL;
echo call_user_func_array('sum', [2, 5]);
1
7
1〜3行目で定義されている関数sum
は、二つの数値をうけとって、それらの和を返すというものです。
これを実行するためにはsum(2, 5)
のように二つの引数を指定する必要があります。
このような場合でも、文字列sum
自体は callable です。
これは5行目の命令によって1
が出力されていることからわかります。
さて、文字列sum
が callable だということは、文字列sum
を関数として呼び出せるということです。
sum
のような引数を必要とする関数を callable によって呼び出したいときは、call_user_func_array
という関数をつかいます。
call_user_func_array
— パラメータの配列を指定してコールバック関数をコールする
第一引数には callable を、第二引数には呼び出される関数にわたしたい式を配列にしたものを指定します。
7行目では、call_user_func_array
の第一引数には callable である文字列sum
を、第二引数には配列[2, 5]
を指定しました。
これによって関数sum
が呼び出され、関数sum
の第一引数には2
が、第二引数には5
がわたされます。
このとき関数sum
は2
と5
の和である7
を返しますので、この7
がecho
されて7
が出力されたというわけです。
**余談・・**
function sum($int1, $int2) {
return $int1 + $int2;
}
echo is_callable('sum') . PHP_EOL;
echo call_user_func('sum');
これを実行すると、もちろんエラーが出るのですが、このときのエラーメッセージはつぎのようになります。
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function sum(), 0 passed in ... and exactly 2 expected in ......
「関数sum
にわたす引数が少なすぎるよ!」といわれています。
ということは、関数sum
の呼び出し自体は問題なく行われたということです。
先ほどみたとおり、文字列sum
自体は callable でした。
ですので、call_user_func
の引数に文字列sum
を指定してあげれば、関数sum
を呼び出すこと自体は問題なくできるというわけです。
例4
$hello = function () {
echo 'こんにちは。';
};
echo is_callable($hello) . PHP_EOL;
call_user_func($hello);
1
こんにちは。
1〜3行目で、変数hello
に無名関数を代入しています。
無名関数は callable です。
これは5行目の命令によって1
が出力されていることからわかります。
一般的なユーザー定義関数とは異なり、 無名関数 もパラメータとして渡せます。
7行目では、call_user_func
に変数hello
の値である無名関数をわたすことによって、その無名関数自身を呼び出しています。
**ちなみに・・**
$hello = function () {
echo 'こんにちは。';
};
var_dump($hello);
object(Closure)#1 (0) {
}
無名関数はPHPが用意しているClosure
という特別なクラスのインスタンスとして実現されています。
無名関数の実装には Closure クラスを使っています。
例5
class Player {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getname() {
return $this->name;
}
}
$ichiro = new Player('イチロー');
echo is_callable([$ichiro, 'getname']) . PHP_EOL;
echo call_user_func([$ichiro, 'getname']);
1
イチロー
1〜10行目で、Player
クラスを定義しています。このクラスのなかでgetname
というメソッドを定義しました。
つづく12行目でPlayer
クラスのインスタンスを作成し、変数ichiro
に代入しています。
このとき、配列[$ichiro, 'getname']
は callable です。
この配列をcall_user_func
の引数に指定することで、変数ichiro
に代入されたPlayer
クラスのインスタンスのgetname
メソッドを呼び出すことができます。
オブジェクトのインスタンスを渡すには配列を使います。 配列の 0 番目の要素にオブジェクトを、 そして 1 番目の要素にメソッド名を指定します。
イチロー
と出力されていることから、所期のメソッドが呼び出されたことがわかりますね。
例6
class Car {
public static function honk() {
echo 'ビッビー';
}
}
echo is_callable(['Car', 'honk']) . PHP_EOL;
call_user_func(['Car', 'honk']);
1
ビッビー
1〜5行目で、Car
クラスを定義し、そのなかでhonk
という静的メソッドを定義しました。
このとき、配列['Car', 'honk']
は callable です。
この配列をcall_user_func
の引数に指定することで、Car
クラスの静的メソッドhonk
を呼び出すことができます。
静的なクラスメソッドの場合、オブジェクトのインスタンスは不要です。 0 番目の要素として、オブジェクトのかわりにクラス名を指定します。
例7
class Car {
public static function honk() {
echo 'ビッビー';
}
}
echo is_callable('Car::honk') . PHP_EOL;
call_user_func('Car::honk');
1
ビッビー
クラスの定義は例6とおなじです。
例6では、配列['Car', 'honk']
が callable であることをたしかめました。
今回の例は、文字列Car::honk
もまた callable であることを表しています。
'ClassName::methodName' 形式で指定することもできます。
クラスの静的メソッドを callable として表現する方法は二種類あるということですね。
おしまい
callable の例をたくさんみてきました。
これで callable とは何なのか、多少なりとも理解が深まったと思います。
また、本記事では説明が不十分な箇所も多々あるかと思います。
疑問に思うところがあったら、適宜 PHP マニュアル等を参照してください。
最後まで読んでいただき、ありがとうございました。