Closed8

PHP 無名関数

chick_tockchick_tock

無名関数 ¶

無名関数はクロージャとも呼ばれ、 関数名を指定せずに関数を作成できるようにするものです。 callable パラメータとして使う際に便利ですが、用途はそれにとどまりません。

無名関数の実装には Closure クラスを使っています。

chick_tockchick_tock

変数の値として使用できる

クロージャは、変数の値として使用することもできます。 PHP は、そのような記述があると自動的に内部クラス Closure のインスタンスに変換します。 変数へのクロージャの代入は、他の代入と同じように記述し、 同じく最後にセミコロンをつけます。

例2 変数への無名関数の代入

<?php
$greet = function($name)
{
    printf("Hello %s\r\n", $name);
};

$greet('World');
$greet('PHP');
?>
chick_tockchick_tock

useを用いて親のスコープから変数を引き継ぐ

クロージャは、変数を親のスコープから引き継ぐことができます。 引き継ぐ変数は、use で渡さなければなりません。 PHP 7.1 以降は、引き継ぐ値に スーパーグローバル や $this、 およびパラメータと同じ名前の変数を含めてはいけません。
戻り値の型は、 use の 後 に置かなければいけません。

例3 親のスコープからの変数の引き継ぎ

<?php
$message = 'hello';

// "use" がない場合
$example = function () {
    var_dump($message);
};
$example();

// $message を引き継ぎます
$example = function () use ($message) {
    var_dump($message);
};
$example();

// 引き継がれた変数の値は、関数が定義された時点のものであり、
// 関数が呼ばれた時点のものではありません
$message = 'world';
$example();

// $message をリセットします
$message = 'hello';

// リファレンス渡しで引き継ぎます
$example = function () use (&$message) {
    var_dump($message);
};
$example();

// 親のスコープで変更された値が、
// 関数呼び出しの内部にも反映されます
$message = 'world';
$example();

// クロージャは、通常の引数も受け付けます
$example = function ($arg) use ($message) {
    var_dump($arg . ' ' . $message);
};
$example("hello");

// 戻り値の型は、use の後に置きます
$example = function () use ($message): string {
    return "hello $message";
};
var_dump($example());
?>

上の例の出力は、 たとえば以下のようになります。

Notice: Undefined variable: message in /example.php on line 6

NULL

string(5) "hello"

string(5) "hello"

string(5) "hello"

string(5) "world"

string(11) "hello world"

string(11) "hello world"
chick_tockchick_tock

##「値渡し」とは、変数に代入した値の"コピー"を渡します。

// 変数bに代入した後に変数aの値を変えても
// 変数bは変わりありません。

$a = 2;
$b = $a;  // 変数aを代入
$a = 10;  // 変数aの値を変更
echo $b;


# 結果
2

「参照渡し」とは、変数に代入した値の”参照先”(= 値の入れ物) を渡します。

// 変数bに代入した後に変数aの値を
// 変えたところ、変数bの値も変わります。

$a = 2;
$b =& $a;  // 変数aを&をつけて代入
$a = 10;    // 変数aの値を変更
echo $b;


# 結果
10
chick_tockchick_tock

Laravel クエリビルダでのクロージャ

判定式によって検索条件を変更する
「リクエストであのパラメータが来た場合は、検索条件にこれを追加する」
のような流れは良くあるパターンです。

Laravelのクエリビルダには、そのパターンでのSQL文組み立てにも対応しています。

when()メソッドを使い、第一引数に判定式の結果(trueもしくはfale)、第二引数にクロージャを指定し、trueであった場合の処理をクロージャに定義します。

$user_id = 8;

$data = $users
    ->when($user_id, function ($query) use ($user_id) {
        return $query->where('id', $user_id);
    })
    ->get();

上記例の場合、
「$user_idがtrue(すなわち、値が入っている)の場合は、idカラムをその値で指定する」
という条件が追加されます。

このスクラップは2022/08/28にクローズされました