はじめに
PHP でクロージャ(無名関数)を使うとき、外側の変数をスコープに取り込むために use
を使います。ところが、この use
には
use ($var)
→ 値をコピーして保持use (&$var)
→ 変数への参照を保持
という重要な違いがあります。この記事では具体例を通して、この挙動の差を整理していきます。
目次
サンプルコード
値渡しの場合
<?php
declare(strict_types=1);
error_reporting(-1);
function hoge(){
$i = 11;
$f = function() use ($i){
echo $i , '<br>';
};
$f();
$i = 22;
$f();
$i = 33;
$f();
}
hoge();
参照渡しの場合
<?php
declare(strict_types=1);
error_reporting(-1);
function hoge(){
$i = 11;
$f = function() use (&$i){
echo $i , '<br>';
};
$f();
$i = 22;
$f();
$i = 33;
$f();
}
hoge();
実行結果の比較
値渡し (use ($i)
) の場合
実行結果
11
11
11
参照渡し (use (&$i)
) の場合
実行結果
11
22
33
解説
use ($i)
はクロージャを定義した時点の値をコピーして保持する。use (&$i)
はクロージャが外側の変数そのものを参照し続けるため、外側で値を変更するとクロージャの中から見える値も変わる。- クロージャ内で変数を書き換える場合も、コピーか参照かで挙動が大きく変わる。
まとめ
- スナップショットを取りたい →
use ($var)
- 外の変数と同期して扱いたい →
use (&$var)
クロージャを使う場面では「コピーするのか、参照するのか」を意識することが大事です。これを理解しておくと、バグの混入を防ぎやすくなります。