0001-01-01
4 min read

closure と callable

Closureとcallable、どちらも無名関数に使えるタイプヒンティングなのですが、callableは無名関数以外でも関数名とかでもいけるけどClosureはそういうのいけないよという話。 http://dekokun.github.io/posts/2014-07-25-2.html

PHPにクロージャがあるのに、__invokeは必要なのか? https://qiita.com/mitsuru793/items/e25b4351e8a63a229b8a

PHP8の名前付き引数はcall_user_func_arrayでも使える https://zenn.dev/rsk/articles/24034fcd27b2572d6c3e

プロパティに格納されたクロージャを呼び出す方法まとめ

【PHP】プロパティに格納されたクロージャを呼び出す方法まとめ https://qiita.com/rhap/items/1701247844772c3c92f0

  private $closure;

  public function call($arg)
  {
    $closure = $this->closure;
    $closure($arg);

    ($this->closure)($arg);

    $this->closure->__invoke($arg);

    call_user_func($this->closure, $arg);

    $this->closure->call($this, $arg);

  }

コールバック型(callable)

  • closure
  • Variable functions(可変関数) “関数名” 名前を文字列で指定する
  • array(“クラス指定”, “メソッド名”),[“クラス指定”, “メソッド名”]
  • array(インスタンス, “メソッド名”),[インスタンス, “メソッド名”]
  • call_user_func
  • call_user_func_array

可変関数を利用したコールバック関数には一つ問題があって、クラスやオブジェクトのメソッドをコールバック関数として渡すことができません。

クロージャ

$closure = function soudayo($option) {
    return "そうだよ({$option})";
};
echo $closure('便乗'); // そうだよ(便乗)

“関数名”

function soudayo($option) {
    return "そうだよ({$option})";
}
$name = 'soudayo';
echo $name('便乗'); // そうだよ(便乗)

可変変数 というものもある

$name = ’name1’; $name1 = ‘hogehoge’;

print $$name;

メンバー変数 class tester_a{ public $a=null; public $b=null; public $valid=array(“a”,“b”); function __construct($params){ foreach($this->valid as $k){

	$this->{$k}=$params[$k];
}

}

}

http://kagigotonet.hatenablog.com/entry/20091215/1260851032

array(“クラス指定”, “メソッド名”)

class MUR {
    public static function soudayo($option) {
        return "そうだよ({$option})";
    }
}
$name = array('MUR', 'soudayo');
echo $name('便乗'); // そうだよ(便乗)

クラスの指定 https://s8a.jp/php-keyword-class#%E3%81%BE%E3%81%A8%E3%82%81

__CLASS__はそれが記述されたクラス名を表すマジック定数

class MUR {
    private static function soudayo($option) {
        return "そうだよ({$option})";
    }
    public static function test() {
        $name = array(__CLASS__, 'soudayo');
        echo $name('便乗'); // そうだよ(便乗)
    }
}
MUR::test();

array(インスタンス, “メソッド名”)

主にインスタンスメソッドのコールに用いられます。

class MUR {
    public function soudayo($option) {
        return "そうだよ({$option})";
    }
}
$mur = new MUR;
$name = array($mur, 'soudayo');
echo $name('便乗'); // そうだよ(便乗)

class MUR {
    private function soudayo($option) {
        return "そうだよ({$option})";
    }
    public function test() {
        $name = array($this, 'soudayo');
        echo $name('便乗'); // そうだよ(便乗)
    }
}
$mur = new MUR;
$mur->test();

call_user_func_array

// $foo->bar() メソッドに引数を 2 つ渡してコールします $foo = new foo; call_user_func_array(array($foo, “bar”), array(“three”, “four”));

call_user_func_array は 下記で代替できる

array($foo, “bar”) , … [“three”, “four”]

スプレッド演算子の最初の利点はフォーマンス改善

クロージャとinvokeの使い分けの基準 https://qiita.com/mitsuru793/items/e25b4351e8a63a229b8a

再利用。メソッドチェーン

利用方法

クロージャーのデザインパターンがある https://blog.sarabande.jp/post/30018909789

無名関数の使いどころ https://notepad-blog.com/content/95/

CSVファイルの出力。フォーマットが違う

Loan パターン リソースがスコープの外に抜け出たときに廃棄されることを保証する。finally 句が追加された PHP 5.5 以降でこのパターンが利用できます。

テーブル表示

call_user_func_arrayを使った共通処理作成

https://qiita.com/annderber/items/d5c261088170d818d47c

https://qiita.com/kd9951/items/2328e2f8add9037bd990

引き渡す変数配列のキーが、インジェクトされるメソッドの引数名で、一致するところに入れてくれます。ちなみに、このキーを省略しても案外柔軟に入れてくれたりしますが、意図しない動作になることがあるのでキーはきちんと入れましょう(Laravel自体がこういった使い方を推奨していない、というウワサもあります)。

最初これが、コントローラのルート定義で ‘/user/{id}’ とするときにやっていることだ!と思いましたが、ルート定義の場合は変数名が一致していなくてもかなり正確に注入してくれます。実はやっていることがちょっと違うんですが……ここでは割愛させていただきます。

app()->call

Previous
Next