コールバック関数を引数に取る関数を定義する - PHP5 プログラミング

PROGRAM


コールバック関数を引数に取る関数を定義する

PHP5 では、コールバック関数やコールバックメソッドを関数の引数に渡して、それを実行することができます。

やりかたとしては、基本的には変数に、呼び出したい関数の情報を文字列等で関数に渡して、それを "call_user_func" 関数で実行するという流れになります。

引数を取るコールバック関数

たとえば、引数を 2 つ取るコールバック関数を呼び出す関数は、つぎのように書くことができます。

function do_callback($callback)

{

// 引数に渡されたコールバック関数 ($callback) が呼び出し可能であることを確認します。

if (is_callable($callback))

{

// 呼び出し可能であればそれを実行します。

call_user_func($callback, 'A', 'B');

}

}

このようにすることで、$callback で渡された関数に対して、2 つの引数 'A' と 'B' とを渡して呼び出すことが可能です。

call_user_func 関数は引数の数を任意に指定できるので、今回は 2 つとなっていますが、5 つにしたり、0 個にしたりといったことも可能です。

 

この関数に実際に関数を渡す場合ですが、たとえば次のような関数があったとします。

function callbackFunction($param1, $param2)

{

echo "$param1=$param2\n";

}

この場合は、次のようにして、呼び出したい関数名を文字列で、先ほど作成したコールバック関数を引数に取る callback 関数に渡します。

do_callback('callbackFunction');

 

続いて、コールバックして欲しい機能がクラスインスタンスが持つメソッドだった場合ですが、たとえば次のようなクラスがあるとします。

class classHasCallback

{

public function callbackMethod($param1, $param2)

{

echo "$param1=$param2\n";

}

}

この場合は、コールバック関数の情報を次のように配列で指定することになります。

// クラスインスタンスがあります。

$class = new classHasCallback();

 

// コールバックしたいメソッドは、連想配列 $インスタンス => '関数名' という形で用意します。

$callback = array($class, 'callbackMethod');

 

// do_callback 関数の引数にコールバックメソッドを渡します。

do_callback($callback);

 

引数を取らないコールバック関数の方法

変数が呼び出し可能かを判定する "is_callable" 関数に備わっている、直接呼出し可能な変数を作成してそれを呼び出す方法もあります。

function do_callback($callback)

{

// 引数に渡されたコールバック関数 ($callback) が呼び出し可能であることを確認します。

if (is_callable($callback, false, $callbackName))

{

// 呼び出し可能であれば、is_callable 関数で取得した $callbackName を直接実行します。

$callbackName;

}

}

is_callable の第二引数に false を指定して、第三引数に変数名を渡してあげると、渡した変数名の中に、関数を直接呼び出すための情報が代入されます。あとはこの変数を参照すれば、そこに登録されているコールバック関数を呼び出すことができます。

ただし、この方法ではコールバック関数に引数を渡すことができないようでした。もし引数を渡そうと、例えば "$callbackName('A', 'B');" などとしてしまうと、次のようなエラーメッセージが表示されてしまいました。

Fatal error: Call to undefined function callback() in C:\test\callback.php on line 32

もっとも、こちらの書き方の方が特段スマートということもありませんし、むしろ call_user_func 関数を使った書き方の方が何をしているのかが分りやすいような気がするので、個人的にはわざわざ is_callables 関数で直接呼出し可能なコールバック関数を取得する必要はないように思います。

 

コールバック関数が参照渡しの引数を取る場合

PHP5 では、いつのバージョンからか、変数の参照渡しは、呼び出し元で変数の参照を引数に指定するのではなく、呼び出し先の関数の定義のときに、どの変数を参照で受け取るかを指定するようになりました。

つまり、変数を次のように定義したら、

function XXXX(&$valueByRef)

{

}

次のように引数を普通に渡すだけで、参照渡しでその関数を呼び出せます。

XXXX($valueByRef)

このときもし "XXXX(&$valueByRef)" のように引数を参照渡しで指定すると、次のようなエラーが表示されてしまいます。

Call-time pass-by-reference has been deprecated in

従来通りのこの渡し方を使いたい場合は、PHP 5.4.0 以前なら php.ini の "allow_call_time_pass_reference" を "On" にすることでも回避出来たりするらしいですが、余程の理由がない限りは、普通はこのような使い方はしません。

 

これは、今回のテーマの call_user_func で関数でも同様なのですが、コールバックする関数の引数が参照渡しを受け取るようになっていた場合には、call_user_func 関数に渡す引数から "&" を取ってしまうと、次のようなエラーになって上手く値を渡せません。

expected to be a reference, value given in

コールバック先の関数へ変数を参照渡しで渡すためには、call_user_func_array 関数を使う必要があります。

 

call_user_func_array は、使い方はほとんど call_user_func と同じですが、コールバック関数に渡す引数を、可変長の引数ではなく配列で渡すところが大きく違います。

そして、引数として渡す配列をそろえる時に、参照渡ししたい変数を "&" を付けて指定します。

call_user_func_array('callbackFunction', array($value, &%reference));

この例では、用意した配列の 2 番目で指定した引数を、コールバック関数 'callbackFunction' に参照渡しで渡しています。

このように、コールバック関数の呼び出しの場合に限っては、呼び出し元で変数の参照渡しをするのを忘れないようにする必要があります。


[ もどる ]