Closureとは何か
PHPにおける Closure(クロージャ) とは、名前を持たない「無名関数」のことです。変数に代入したり、他の関数へ引数として渡したり、関数の戻り値として返したりすることができます。
PHP 5.3 で導入され、PHP 7・8 と進化を重ねながら今日のPHP開発で欠かせない機能となっています。
<?php
// 変数に代入するシンプルなClosure
$greet = function (string $name): string {
return "こんにちは、{$name}さん!";
};
echo $greet("田中"); // こんにちは、田中さん!
通常の関数と同じようにパラメータや戻り値の型宣言を付けることができます。
useキーワードで外側のスコープを取り込む
通常の関数と大きく異なるのが、use キーワードを使って外側のスコープにある変数を取り込める点です。
<?php
$prefix = "【お知らせ】";
$buildMessage = function (string $text) use ($prefix): string {
return $prefix . $text;
};
echo $buildMessage("本日は休業です。");
// 【お知らせ】本日は休業です。
デフォルトでは値渡しです。クロージャの生成時点の値がコピーされます。
<?php
$count = 0;
$increment = function () use ($count): void {
echo $count . "\n"; // 常に 0 が出力される
};
$count = 10;
$increment(); // 0
参照渡しにしたい場合は & を付けます。
<?php
$count = 0;
$increment = function () use (&$count): void {
$count++;
};
$increment();
$increment();
echo $count; // 2
アロー関数(Arrow Function)
PHP 7.4 で追加された アロー関数 は、fn キーワードを使ったよりシンプルな書き方です。外側のスコープの変数を 自動的に値渡しで取り込む 点が特徴です。
<?php
$multiplier = 3;
$triple = fn(int $n): int => $n * $multiplier;
echo $triple(5); // 15
use を明示的に書く必要がなく、単一式であればスッキリ記述できます。複数行の処理が必要な場合は従来の無名関数を使いましょう。
実践的な活用パターン
コールバックとして渡す
array_map や array_filter などの配列関数と組み合わせるのが典型的な使い方です。
<?php
$prices = [100, 250, 80, 430, 60];
// 100円以上の価格だけを抽出
$filtered = array_filter($prices, fn(int $price): bool => $price >= 100);
// 10%引きに変換
$discounted = array_map(fn(int $price): int => (int)($price * 0.9), $filtered);
print_r($discounted);
// Array ( [0] => 90 [1] => 225 [3] => 387 )
クロージャを返す関数(ファクトリパターン)
クロージャを返す関数を作ることで、動的に振る舞いを変えた関数を生成できます。
<?php
function makeGreeter(string $language): Closure
{
return match ($language) {
'en' => fn(string $name): string => "Hello, {$name}!",
'fr' => fn(string $name): string => "Bonjour, {$name}!",
default => fn(string $name): string => "こんにちは、{$name}さん!",
};
}
$greetJa = makeGreeter('ja');
$greetEn = makeGreeter('en');
echo $greetJa("佐藤"); // こんにちは、佐藤さん!
echo $greetEn("Smith"); // Hello, Smith!
Closure::bindToでオブジェクトに束縛する
Closure::bindTo() を使うと、クロージャを特定のオブジェクトに紐付けて $this を使えるようにできます。
<?php
class User
{
private string $name;
private int $age;
public function __construct(string $name, int $age)
{
$this->name = $name;
$this->age = $age;
}
}
$getProfile = function (): string {
return "{$this->name}({$this->age}歳)";
};
$user = new User("山田", 28);
$bound = Closure::bind($getProfile, $user, User::class);
echo $bound(); // 山田(28歳)
クラスの外部からプライベートプロパティにアクセスできる強力な機能です。テストやデバッグ目的で使われることがあります。
静的クロージャ
static を付けると $this を持たない 静的クロージャ を定義できます。オブジェクトに束縛されないため、不用意なメモリの保持を防ぎます。
<?php
$add = static function (int $a, int $b): int {
return $a + $b;
};
echo $add(3, 7); // 10
オブジェクトコンテキストが不要な場合は積極的に static を付けるとコードの意図が明確になります。
まとめ
| 機能 | 説明 |
|---|---|
| 無名関数 | function で定義、変数や引数として利用可能 |
use | 外側スコープの変数を値渡しまたは参照渡しで取り込む |
| アロー関数 | fn による短縮構文、外側変数を自動取り込み |
Closure::bind | オブジェクトへの束縛で $this を使えるように |
| 静的クロージャ | static で $this を持たないクロージャを定義 |
Closure を使いこなすことで、コールバック処理・ファクトリパターン・遅延評価など様々な場面でコードをよりシンプルかつ柔軟に書けるようになります。ぜひ日常の実装に取り入れてみてください。