ねこさんとへびさんの新人技術ブログ

新人エンジニアのねこさんとへびさんの、技術向上のためのブログです。

Memo!無名関数と変数のスコープ - PHP

PHPの無名関数の実装は、クロージャが使われています。

クロージャはローカルスコープの外で定義された、引数以外の変数を利用することができます。
引数以外の変数を利用したい場合は、useを使って渡します。

<?php
$greeting = "Good morning";

$greet_nouse_use = function()
{
    error_log("message: " . $greeting);
};


$greet_use_use = function() use ($greeting)
{
    error_log("message: " . $greeting);
};

このコードの実行結果を見てみましょう。
useを使わない無名関数は親スコープの$greeting変数の値を参照できないですし、
使っている無名関数は参照できています。

message:
message: Good morning


クロージャの特徴として、引数以外の変数を実行時ではなく、自分が定義された時点で解決するという特徴があります。
下のコードでは無名関数$greetが定義された時点で変数$greetingの値はGood morning、
実行の時点ではHelloです。
PHPの無名関数はクロージャですから、Helloが代入されたあとに実行された$greet()は、Good morningを出力します。

<?php
$greeting = "Good morning";

$greet = function () use ($greeting) {
    error_log("message: " . $greeting);
};

$greeting = 'Hello';
$greet();

message: Good morning


useには参照渡しが使えるので、実行時点の変数を使いたければ参照渡しにして変数を引き継ぎましょう。

<?php
$greeting = "Good morning";

$greet = function () use (&$greeting) {
    error_log("message: " . $greeting);
};

$greeting = 'Hello';
$greet();

$greeting = 'Good night';
$greet();

message: Hello
message: Good night


もちろん引数と一緒に使えます!

<?php
$greeting = "Good morning";

$greet = function ($name) use ($greeting) {
    error_log($name . ', ' . $greeting);
};

$greet('Hebisan');

Hebisan, Good morning

(byへびさん)