PHPの匿名関数でuseキーワードを使って親スコープの変数にアクセスする方法
PHPでは、useキーワードを使うことで、匿名関数(クロージャ)の中に親スコープの変数を取り込む(バインドする)ことができます。
匿名関数のスコープに外部の変数を引き継ぎたい場合は、関数定義時に use キーワードで変数を指定します。
コード例
<?php
$message = 'hello there';
$example = function () {
var_dump($message);
};
$example();
$example = function () use ($message) { // $message を引き継ぐ
var_dump($message);
};
$example();
// 引き継いだ変数の値は「関数が定義された時点」のものであり、
// 「呼び出された時点」のものではない
$message = 'Inherited value';
$example();
$message = 'reset to hello'; // メッセージをリセット
$example = function () use (&$message) { // 参照渡しで引き継ぐ
var_dump($message);
};
$example();
// 親スコープで変更された値は
// 関数呼び出しの中にも反映される
$message = 'change reflected in parent scope';
$example();
$example("hello message");
?>
出力結果
このコードを実行すると、次のような出力が得られます。
NULL string(11) "hello there" string(11) "hello there" string(14) "reset to hello" string(32) "change reflected in parent scope" string(32) "change reflected in parent scope"
動作の解説
まず最初に、use を使っていない $example 関数が呼び出されます。この関数のスコープ内には $message が存在しないため、NULL が出力されます。
次に、use ($message) によって $message を値渡しで引き継いだ関数が定義されます。ここで重要なのは、引き継がれるのは関数を定義した時点の値だという点です。そのため、その後に $message の値を変更しても、関数の出力には反映されず、"hello there" のまま出力されます。
一方、use (&$message) のように参照渡しで引き継ぐと挙動が変わります。親スコープ側で値が変更されると、その変更が関数内にも反映されるため、"reset to hello" や "change reflected in parent scope" のように、呼び出し時点の最新の値が出力されます。
なお、最後の $example("hello message") では引数を渡していますが、このクロージャは引数を受け取る定義になっていないため、渡された値は単に無視され、同じ結果が出力されます。
ポイントまとめ
useキーワードを使うと、匿名関数に親スコープの変数を引き継げる- デフォルト(値渡し)の場合、引き継がれるのは関数定義時の値のコピー
&を付けて参照渡しにすると、呼び出し時の最新の値が使われる- クロージャが受け付けない引数を渡しても、その値は無視される
-
PHPで匿名クラスを使ってオブジェクトを作成する方法
PHP 7以降では、名前を持たない「匿名クラス(無名クラス)」を作成できるようになりました。PHPではすべてのオブジェクトが何らかのクラスと関連付けられていますが、匿名クラスも通常のクラスと同様にインスタンス化してオブジェクトを生成することが可能です。匿名クラスの基本構文匿名クラスは new class という構文で定義します。クラス名を宣言することなく、その場でオブジェクトを生成できるのが大きな特徴です。他のクラスと同じように、extends を使って既存のクラスを継承することもできます。サンプルコード<?php class my_sample_class {}
-
PHPのextract()関数とは?使い方とパラメータを徹底解説
extract()関数とはPHPのextract()関数は、配列のキーと値を現在のシンボルテーブルに変数としてインポートする関数です。連想配列の各要素が「キー名=変数名、値=変数の値」として展開され、戻り値としては正常に抽出された変数の個数が返されます。構文extract(arr, rules, prefix)パラメータarr − 変数として展開したい対象の配列を指定します。rules − 無効な変数名や既存変数との衝突(コンフリクト)が発生した場合の扱い方を指定します。指定できる値は以下の通りです。EXTR_OVERWRITE − デフォルト値。同名の変数が既に存在する場合、既存の変数を上書