PHP - callable

コールバック / Callable

コールバックは、callable タイプヒントで表されます。call_user_func()usort() などの関数は、ユーザが定義するコールバック関数を引数とします。コールバック関数は、単純な関数だけでなく、オブジェクトのメソッド、あるいはクラスの静的メソッドであってもかまいません。

PHP 関数はその名前を単に文字列として渡します。どのようなビルトインまたはユーザ定義の関数も渡すことができます。ただし、array(), echo, empty(), eval(), exit(), isset(), list(), print, unset() といった言語構造はコールバックとしては使えません。

オブジェクトのインスタンスを渡すには配列を使います。配列の 0 番目の要素にオブジェクト、 そして 1 番目の要素にメソッド名を指定します。

一般的なユーザ定義関数とは異なり、無名関数とアロー関数もパラメータとして渡せます。

<?php
  // コールバック関数の例
  function my_callback_function() {
      echo 'hello world!';
  }

  // 単純なコールバック
  call_user_func('my_callback_function'); // hello world!
?>
単純なコールバック

静的なクラスメソッドの場合、オブジェクトのインスタンスは不要です。0 番目の要素として、オブジェクトのかわりにクラス名を指定します。'ClassName::methodName' 形式で指定することもできます。

<?php
  // コールバックメソッドの例
  class MyClass {
      static function myCallbackMethod() {
          echo 'Hello World!';
      }
  }

  // 静的クラスメソッドのコール
  call_user_func(array('MyClass', 'myCallbackMethod')); // Hello World!
?>
静的クラスメソッドのコール
<?php
  // コールバックメソッドの例
  class MyClass {
      static function myCallbackMethod() {
          echo 'Hello World!';
      }
  }

  // オブジェクトメソッドのコール
  $obj = new MyClass();
  call_user_func(array($obj, 'myCallbackMethod')); // Hello World!
?>
オブジェクトメソッドのコール
<?php
  // 相対指定による静的クラスメソッドのコール
  class A {
      public static function who() {
          echo "A";
      }
  }

  class B extends A {
      public static function who() {
          echo "B";
      }
  }

  call_user_func(array('B', 'parent::who')); // A
?>
相対指定による静的クラスメソッドのコール

__invoke() を実装した任意のオブジェクトもパラメータとして渡せます。

<?php
  // __invoke を実装したオブジェクトを callable として用いる
  class C {
      public function __invoke($name) {
          echo 'Hello ', "$name";
      }
  }

  $c = new C();
  call_user_func($c, 'PHP!'); // Hello PHP!
?>
__invoke を実装したオブジェクトを callable として用いる

クロージャを使ったコールバックの例は以下になります。

<?php
  // クロージャ
  $double = function($a) {
      return $a * 2;
  };

  // 数値の範囲
  $numbers = range(1, 5);

  // クロージャをコールバックとして指定
  $new_numbers = array_map($double, $numbers);

  print implode(' ', $new_numbers); // 2 4 6 8 10
?>
クロージャを使ったコールバックの例

関連記事