PHPで「ラムダ式」と呼ばれるものは、主に無名関数やアロー関数のことです。
名前を付けて定義する通常の関数とは異なり、ラムダ式は関数名を持たず、その場で定義して使える関数です。
配列の要素を変換したり、条件に合うデータだけを抽出したり、コールバック処理を渡したりするときによく使われます。
PHP公式の用語としては、「ラムダ式」よりも次の言葉がよく使われます。
| 用語 | 意味 |
|---|---|
| 無名関数 | 名前を持たない関数 |
| クロージャ | 無名関数として扱われる関数オブジェクト。外側の変数を取り込める |
| アロー関数 | fn を使って短く書ける無名関数の構文 |
PHPでは、無名関数やアロー関数は Closure クラスのオブジェクトとして扱われます。
PHPのラムダ式の基本
通常の関数との違い
まず、通常の関数は次のように名前を付けて定義します。
function double($num) {
return $num * 2;
}
echo double(5); // 10
一方、ラムダ式では関数名を付けずに定義できます。
$double = function ($num) {
return $num * 2;
};
echo $double(5); // 10
この例では、function ($num) { ... } の部分が無名関数です。
無名関数を $double という変数に代入し、$double(5) のように呼び出しています。
無名関数の基本構文
PHPの無名関数は、次のように書きます。
$変数名 = function (引数) {
処理;
return 戻り値;
};
たとえば、2つの数値を足す関数は次のように書けます。
$add = function ($a, $b) {
return $a + $b;
};
echo $add(3, 5); // 8
ポイントは、無名関数を変数に代入しているため、最後にセミコロン ; が必要になることです。
$add = function ($a, $b) {
return $a + $b;
};
通常の関数定義では最後にセミコロンを書きませんが、無名関数を変数に代入する場合は、代入文として扱われるためセミコロンが必要です。
無名関数とは
名前を持たない関数
無名関数とは、名前のない関数のことです。
通常の関数は次のように名前があります。
function greet($name) {
return $name . 'さん、こんにちは';
}
しかし、無名関数には関数名がありません。
$greet = function ($name) {
return $name . 'さん、こんにちは';
};
echo $greet('田中'); // 田中さん、こんにちは
function greet($name) ではなく、function ($name) と書いている点が特徴です。
無名関数を変数に代入する
無名関数は、変数に代入して使えます。
$hello = function () {
return 'Hello';
};
echo $hello(); // Hello
このように、変数名の後ろに () を付けることで、関数として実行できます。
$hello();
変数の中に関数そのものが入っている、と考えると分かりやすいです。
無名関数を関数の引数として渡す
無名関数は、他の関数に引数として渡すこともできます。
function apply($value, $callback) {
return $callback($value);
}
$result = apply(10, function ($num) {
return $num * 3;
});
echo $result; // 30
この例では、apply() に「10を3倍にする処理」を渡しています。
このように、関数に別の関数を渡す仕組みをコールバックと呼びます。
PHPのラムダ式は、このコールバック処理でよく使われます。
クロージャとは
PHPにおけるクロージャの考え方
PHPでは、無名関数は Closure クラスのオブジェクトとして実装されています。
実務上は、特に外側のスコープにある変数を取り込んで使える無名関数をクロージャとして説明することが多いです。
たとえば、次のようなケースです。
$tax = 1.1;
$calc = function ($price) use ($tax) {
return $price * $tax;
};
echo $calc(1000); // 1100
このコードでは、無名関数の外側にある $tax を、関数の中で使っています。
ただし、通常の無名関数では外側の変数を自動的には使えません。
外側の変数を使うには、use を使って明示的に取り込む必要があります。
useで外側の変数を取り込む
無名関数の外側にある変数を使いたい場合は、次のように use を書きます。
$message = 'こんにちは';
$greet = function ($name) use ($message) {
return $message . '、' . $name . 'さん';
};
echo $greet('田中'); // こんにちは、田中さん
use ($message) と書くことで、外側の $message を無名関数の中で使えるようになります。
もし use を書かずに次のようにすると、無名関数の中では $message が未定義変数として扱われます。
$message = 'こんにちは';
$greet = function ($name) {
return $message . '、' . $name . 'さん';
};
echo $greet('田中');
PHP 8.0以降では、未定義変数を使った場合に Undefined variable の警告が出ます。
useは定義時点の値を取り込む
use で取り込まれる値は、基本的に無名関数を定義した時点の値です。
$rate = 1.1;
$calc = function ($price) use ($rate) {
return $price * $rate;
};
$rate = 1.2;
echo $calc(1000); // 1100
このコードでは、途中で $rate を 1.2 に変更しています。
しかし、無名関数の中で使われる $rate は、定義時点の 1.1 です。
そのため、結果は 1200 ではなく 1100 になります。
参照渡しで外側の変数を変更する
外側の変数そのものを変更したい場合は、& を付けて参照渡しにします。
$count = 0;
$increment = function () use (&$count) {
$count++;
};
$increment();
$increment();
echo $count; // 2
use (&$count) と書くことで、無名関数の外側にある $count 自体を変更できます。
ただし、参照渡しは便利な一方で、どこで値が変わったのか分かりにくくなることがあります。
実務では、必要な場合だけ使うのがおすすめです。
アロー関数とは
アロー関数の基本構文
アロー関数は、PHP 7.4から使えるようになった、無名関数を短く書くための構文です。
基本形は次の通りです。
fn (引数) => 式
たとえば、数値を2倍にする処理は次のように書けます。
$double = fn ($num) => $num * 2;
echo $double(5); // 10
これは、次の無名関数と似た意味になります。
$double = function ($num) {
return $num * 2;
};
echo $double(5); // 10
アロー関数では、return を書きません。=> の右側に書いた式が、そのまま戻り値になります。
アロー関数ではreturnを書かない
アロー関数では、次のように書きます。
$add = fn ($a, $b) => $a + $b;
次のように return を書くことはできません。
// 誤り
$add = fn ($a, $b) => return $a + $b;
アロー関数は、短い式をそのまま返すための構文です。
アロー関数は外側の変数を自動で使える
無名関数では、外側の変数を使うために use が必要でした。
$tax = 1.1;
$calc = function ($price) use ($tax) {
return $price * $tax;
};
echo $calc(1000); // 1100
一方、アロー関数では外側の変数を自動的に使えます。
$tax = 1.1;
$calc = fn ($price) => $price * $tax;
echo $calc(1000); // 1100
use ($tax) と書かなくても、外側にある $tax を使えるのがアロー関数の特徴です。
アロー関数の変数キャプチャは値渡し
アロー関数は外側の変数を自動で使えますが、基本的には値渡しで取り込みます。
そのため、外側の変数を書き換える用途には向いていません。
$count = 0;
$increment = fn () => $count++;
$increment();
echo $count; // 0
この例では、$count++ と書いていますが、外側の $count は変更されません。
外側の変数を変更したい場合は、次のように無名関数で参照渡しを使います。
$count = 0;
$increment = function () use (&$count) {
$count++;
};
$increment();
echo $count; // 1
無名関数とアロー関数の違い
書き方の違い
無名関数は次のように書きます。
$double = function ($num) {
return $num * 2;
};
アロー関数は次のように書きます。
$double = fn ($num) => $num * 2;
アロー関数のほうが短く書けます。
外側の変数の扱いの違い
無名関数では、外側の変数を使うために use が必要です。
$rate = 1.1;
$calc = function ($price) use ($rate) {
return $price * $rate;
};
アロー関数では、外側の変数を自動で使えます。
$rate = 1.1;
$calc = fn ($price) => $price * $rate;
ただし、アロー関数の変数キャプチャは値渡しです。
外側の変数を直接変更したい場合は、通常の無名関数を使うほうが分かりやすいです。
複数行の処理を書けるかどうか
無名関数では、複数行の処理を書けます。
$formatPrice = function ($price) {
$taxRate = 1.1;
$priceWithTax = $price * $taxRate;
return number_format($priceWithTax) . '円';
};
echo $formatPrice(1000); // 1,100円
一方、アロー関数は基本的に1つの式を返すための構文です。
$formatPrice = fn ($price) => number_format($price * 1.1) . '円';
echo $formatPrice(1000); // 1,100円
短い処理ならアロー関数が便利ですが、途中で変数を作ったり、条件分岐を複数書いたりする場合は、無名関数のほうが読みやすくなります。
使い分けの目安
無名関数とアロー関数は、次のように使い分けるとよいです。
| 種類 | 向いている処理 |
|---|---|
| 無名関数 | 複数行の処理、複雑な条件、参照渡しを使う処理 |
| アロー関数 | 1行で書ける単純な変換・判定処理 |
たとえば、単純に配列の値を2倍にするだけなら、アロー関数が向いています。
$result = array_map(fn ($num) => $num * 2, $numbers);
一方、複数の処理を行う場合は、無名関数のほうが適しています。
$result = array_map(function ($user) {
$name = trim($user['name']);
return mb_strtoupper($name);
}, $users);
PHPのラムダ式を配列処理で使う
array_mapで使う
array_map() は、配列の各要素に処理を適用して、新しい配列を作る関数です。
$numbers = [1, 2, 3, 4, 5];
$result = array_map(function ($num) {
return $num * 2;
}, $numbers);
print_r($result);
出力は次のようになります。
Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 8
[4] => 10
)
アロー関数を使うと、さらに短く書けます。
$numbers = [1, 2, 3, 4, 5];
$result = array_map(fn ($num) => $num * 2, $numbers);
print_r($result);
array_map() は、先にコールバック関数を書き、その後に配列を指定します。
array_map(コールバック関数, 配列);
array_filterで使う
array_filter() は、条件に合う要素だけを残す関数です。
$numbers = [1, 2, 3, 4, 5, 6];
$evenNumbers = array_filter($numbers, function ($num) {
return $num % 2 === 0;
});
print_r($evenNumbers);
出力は次のようになります。
Array
(
[1] => 2
[3] => 4
[5] => 6
)
この例では、偶数だけを抽出しています。
アロー関数で書くと、次のようになります。
$numbers = [1, 2, 3, 4, 5, 6];
$evenNumbers = array_filter($numbers, fn ($num) => $num % 2 === 0);
print_r($evenNumbers);
array_filter() は、先に配列を書き、その後にコールバック関数を指定します。
array_filter(配列, コールバック関数);
array_map() とは引数の順番が違うため注意しましょう。
array_filterはキーを保持する
array_filter() は、条件に合わない要素を削除したあとも、元の配列のキーを保持します。
$numbers = [1, 2, 3, 4];
$result = array_filter($numbers, fn ($num) => $num % 2 === 0);
print_r($result);
出力は次のようになります。
Array
(
[1] => 2
[3] => 4
)
キーが [0] と [1] に振り直されるわけではありません。
キーを連番にしたい場合は、array_values() を使います。
$numbers = [1, 2, 3, 4];
$result = array_values(
array_filter($numbers, fn ($num) => $num % 2 === 0)
);
print_r($result);
出力は次のようになります。
Array
(
[0] => 2
[1] => 4
)
APIのレスポンスやJSON化する配列では、キーが飛んでいると意図しない形になることがあります。
必要に応じて array_values() でキーを振り直すと安心です。
array_reduceで使う
array_reduce() は、配列の値を1つの結果にまとめる関数です。
$numbers = [1, 2, 3, 4, 5];
$total = array_reduce($numbers, function ($carry, $num) {
return $carry + $num;
}, 0);
echo $total; // 15
$carry は途中経過、$num は現在処理している要素です。
アロー関数を使うと、次のように書けます。
$numbers = [1, 2, 3, 4, 5];
$total = array_reduce($numbers, fn ($carry, $num) => $carry + $num, 0);
echo $total; // 15
合計値の計算、文字列の連結、配列データの集約などに使えます。
PHPのラムダ式をコールバックで使う
コールバックとは
コールバックとは、別の関数に渡して、あとから呼び出してもらう関数のことです。
PHPでは、次のような関数でコールバックがよく使われます。
| 関数 | 用途 |
|---|---|
array_map() | 配列の各要素を変換する |
array_filter() | 条件に合う要素だけ残す |
array_reduce() | 配列を1つの値にまとめる |
preg_replace_callback() | 正規表現に一致した部分を関数で置換する |
usort() | 独自ルールで配列を並び替える |
ラムダ式は、こうしたコールバック処理と相性がよいです。
preg_replace_callbackで使う
preg_replace_callback() は、正規表現に一致した部分を、コールバック関数で置換する関数です。
$text = 'hello-world';
$result = preg_replace_callback('/-([a-z])/', function ($matches) {
return strtoupper($matches[1]);
}, $text);
echo $result; // helloWorld
この例では、hello-world の -w に一致した部分を W に変換しています。
アロー関数で書くと、次のようになります。
$text = 'hello-world';
$result = preg_replace_callback(
'/-([a-z])/',
fn ($matches) => strtoupper($matches[1]),
$text
);
echo $result; // helloWorld
短い変換処理であれば、アロー関数のほうがすっきり書けます。
usortで使う
usort() は、配列を独自のルールで並び替えるときに使います。
$users = [
['name' => '田中', 'age' => 25],
['name' => '佐藤', 'age' => 17],
['name' => '鈴木', 'age' => 32],
];
usort($users, function ($a, $b) {
return $a['age'] <=> $b['age'];
});
print_r($users);
この例では、年齢の昇順で並び替えています。
アロー関数を使うと、次のように短く書けます。
usort($users, fn ($a, $b) => $a['age'] <=> $b['age']);
<=> は宇宙船演算子と呼ばれ、左辺が小さい場合は -1、等しい場合は 0、大きい場合は 1 を返します。並び替えの比較処理でよく使われます。
型宣言とラムダ式
引数と戻り値に型を付ける
PHPのラムダ式では、通常の関数と同じように型宣言を使えます。
$add = function (int $a, int $b): int {
return $a + $b;
};
echo $add(3, 5); // 8
アロー関数でも型宣言を使えます。
$add = fn (int $a, int $b): int => $a + $b;
echo $add(3, 5); // 8
型宣言を付けることで、引数や戻り値の意図が明確になります。
callable型を使う
ラムダ式を関数の引数として受け取る場合は、callable 型を使えます。
function apply(int $value, callable $callback): int {
return $callback($value);
}
$result = apply(10, fn ($num) => $num * 3);
echo $result; // 30
callable は、「呼び出し可能なもの」を表す型です。
たとえば、次のようなものが callable として扱えます。
function double($num) {
return $num * 2;
}
echo apply(10, 'double'); // 20
無名関数やアロー関数だけでなく、関数名の文字列や、オブジェクトのメソッドなども callable として渡せます。
Closure型を使う
Closure 型を指定すると、無名関数やアロー関数のような Closure オブジェクトを受け取ることを明示できます。
function apply(int $value, Closure $callback): int {
return $callback($value);
}
$result = apply(10, fn ($num) => $num * 2);
echo $result; // 20
callable は「呼び出せるもの」全般を表します。
一方、Closure はその中でも、無名関数やアロー関数などの関数オブジェクトを表します。
実務では、広くコールバックを受け取りたい場合は callable、無名関数やアロー関数に限定したい場合は Closure を使うとよいです。
callableとClosureの違い
callableは呼び出し可能なもの全般
callable は、呼び出し可能なものを広く表します。
たとえば、次のようなものが callable です。
function hello() {
return 'Hello';
}
$callback = 'hello';
echo $callback(); // Hello
オブジェクトのメソッドも callable として扱えます。
class Greeter
{
public function hello()
{
return 'Hello';
}
}
$greeter = new Greeter();
$callback = [$greeter, 'hello'];
echo $callback(); // Hello
このように、callable はかなり広い概念です。
Closureは無名関数やアロー関数の実体
Closure は、無名関数やアロー関数の実体です。
$func = function () {
return 'Hello';
};
var_dump($func instanceof Closure); // true
アロー関数も Closure です。
$func = fn () => 'Hello';
var_dump($func instanceof Closure); // true
つまり、Closure は callable の一種と考えると分かりやすいです。
first-class callable構文
PHP 8.1以降で使える構文
PHP 8.1以降では、既存の関数やメソッドから Closure を作るために、first-class callable構文を使えます。
たとえば、次のような関数があるとします。
function double($num) {
return $num * 2;
}
この関数を Closure として扱いたい場合、PHP 8.1以降では次のように書けます。
$double = double(...);
echo $double(5); // 10
double(...) と書くことで、double 関数を Closure として変数に代入できます。
メソッドでも使える
クラスのメソッドでも使えます。
class Calculator
{
public function double($num)
{
return $num * 2;
}
}
$calculator = new Calculator();
$double = $calculator->double(...);
echo $double(5); // 10
これは厳密にはラムダ式そのものではなく、既存の関数やメソッドを Closure として扱うための構文です。
ただし、ラムダ式やコールバック処理と一緒に使われることがあるため、関連知識として覚えておくと便利です。
クラス内でラムダ式を使う場合
アロー関数で$thisを使う
クラスのメソッド内でラムダ式を使う場合、$this を利用できます。
class UserService
{
private string $prefix = 'User: ';
public function formatNames(array $names): array
{
return array_map(fn ($name) => $this->prefix . $name, $names);
}
}
$service = new UserService();
print_r($service->formatNames(['Tanaka', 'Sato']));
この例では、アロー関数の中で $this->prefix を使っています。
クラス内で配列を加工するとき、アロー関数はよく使われます。
static functionとstatic fnに注意する
無名関数やアロー関数には、static を付けることもできます。
$func = static function () {
return 'Hello';
};
$func = static fn () => 'Hello';
ただし、static function や static fn では $this は使えません。
class UserService
{
private string $prefix = 'User: ';
public function formatNames(array $names): array
{
return array_map(static fn ($name) => $this->prefix . $name, $names);
}
}
このような書き方はできません。
$this を使いたい場合は、static を付けないようにしましょう。
ラムダ式を使うメリット
コードを短く書ける
ラムダ式を使うと、短い処理を簡潔に書けます。
$numbers = [1, 2, 3];
$result = array_map(fn ($num) => $num * 2, $numbers);
このような単純な処理のために、わざわざ名前付き関数を定義する必要はありません。
通常の関数で書くと、次のようになります。
function double($num) {
return $num * 2;
}
$result = array_map('double', $numbers);
もちろんこれでも問題ありませんが、一度しか使わない処理であれば、ラムダ式のほうが簡潔です。
処理をその場で定義できる
ラムダ式の大きなメリットは、必要な場所で処理をそのまま書けることです。
$activeUsers = array_filter($users, fn ($user) => $user['status'] === 'active');
このコードを見ると、「アクティブなユーザーだけを抽出している」とすぐに分かります。
処理内容が短ければ、別の場所に関数を定義するよりも読みやすくなります。
コールバック処理を書きやすい
PHPでは、コールバックを受け取る関数が多くあります。
ラムダ式を使うことで、その場で処理を渡せます。
$validators = [
'name' => fn ($value) => $value !== '',
'age' => fn ($value) => $value >= 20,
];
var_dump($validators['name']('田中')); // true
var_dump($validators['age'](18)); // false
このように、バリデーションルールを関数として配列に持たせることもできます。
外側の値を使いやすい
アロー関数では、外側の変数を自動で使えます。
$minAge = 20;
$adults = array_filter($users, fn ($user) => $user['age'] >= $minAge);
無名関数で書く場合は、use が必要です。
$minAge = 20;
$adults = array_filter($users, function ($user) use ($minAge) {
return $user['age'] >= $minAge;
});
短い処理で外側の値を使いたい場合は、アロー関数が便利です。
ラムダ式を使うときの注意点
複雑な処理を書くと読みにくい
ラムダ式は便利ですが、何でもラムダ式で書けばよいわけではありません。
たとえば、次のように条件が長くなると読みにくくなります。
$result = array_filter($users, fn ($user) => $user['age'] >= 20 && $user['status'] === 'active' && $user['email_verified'] === true);
この程度ならまだ読めますが、条件がさらに増えると、コードの意図が分かりにくくなります。
その場合は、名前付き関数やメソッドに切り出したほうがよいです。
function isCampaignTarget(array $user): bool
{
return $user['age'] >= 20
&& $user['status'] === 'active'
&& $user['email_verified'] === true;
}
$result = array_filter($users, 'isCampaignTarget');
関数名があることで、「キャンペーン対象者を判定している」という意味が伝わりやすくなります。
アロー関数は複数文に向かない
アロー関数は1つの式を返すための構文です。
次のような複数文の処理は書けません。
// 誤り
$formatName = fn ($name) => {
$trimmed = trim($name);
return mb_strtoupper($trimmed);
};
この場合は、無名関数を使います。
$formatName = function ($name) {
$trimmed = trim($name);
return mb_strtoupper($trimmed);
};
短い処理はアロー関数、複数行の処理は無名関数、と覚えておくとよいです。
外側の変数を変更する処理は慎重に使う
無名関数では、参照渡しを使うことで外側の変数を変更できます。
$count = 0;
$increment = function () use (&$count) {
$count++;
};
ただし、外側の変数を関数内で変更すると、副作用が増えます。
副作用が多いコードは、あとから読んだときに「どこで値が変わったのか」が分かりにくくなります。
そのため、外側の変数を変更する設計は必要最小限にしたほうがよいです。
セミコロンを忘れない
無名関数やアロー関数を変数に代入する場合、最後にセミコロンが必要です。
$double = function ($num) {
return $num * 2;
};
アロー関数でも同じです。
$double = fn ($num) => $num * 2;
通常の関数定義とは違い、変数への代入文なので、最後の ; を忘れないようにしましょう。
実務での使い分け
1行で終わる処理はアロー関数
単純な変換や判定であれば、アロー関数が向いています。
$names = array_map(fn ($user) => $user['name'], $users);
$adults = array_filter($users, fn ($user) => $user['age'] >= 20);
$pricesWithTax = array_map(fn ($price) => $price * 1.1, $prices);
このように、1行で意味が分かる処理なら、アロー関数を使うとコードがすっきりします。
複数行の処理は無名関数
途中で変数を作ったり、複数の処理を行ったりする場合は、無名関数が向いています。
$formattedUsers = array_map(function ($user) {
$name = trim($user['name']);
$age = (int) $user['age'];
return "{$name}({$age}歳)";
}, $users);
アロー関数で無理に短く書くよりも、無名関数で複数行に分けたほうが読みやすくなります。
意味のある処理は名前付き関数やメソッド
ビジネスロジックとして意味がある処理は、ラムダ式ではなく、名前付き関数やメソッドに切り出すのがおすすめです。
class UserService
{
public function isCampaignTarget(array $user): bool
{
return $user['age'] >= 20
&& $user['status'] === 'active'
&& $user['email_verified'] === true;
}
public function filterCampaignTargets(array $users): array
{
return array_filter($users, [$this, 'isCampaignTarget']);
}
}
isCampaignTarget() という名前があることで、処理の意味が明確になります。
ラムダ式は便利ですが、処理の意味を名前で表したほうが分かりやすい場面では、メソッド化したほうが保守しやすくなります。
ラムダ式の実用例
ユーザー名だけを取り出す
$users = [
['id' => 1, 'name' => '田中'],
['id' => 2, 'name' => '佐藤'],
['id' => 3, 'name' => '鈴木'],
];
$names = array_map(fn ($user) => $user['name'], $users);
print_r($names);
出力は次のようになります。
Array
(
[0] => 田中
[1] => 佐藤
[2] => 鈴木
)
20歳以上のユーザーだけを抽出する
$users = [
['name' => '田中', 'age' => 25],
['name' => '佐藤', 'age' => 17],
['name' => '鈴木', 'age' => 32],
];
$adults = array_values(
array_filter($users, fn ($user) => $user['age'] >= 20)
);
print_r($adults);
array_filter() はキーを保持するため、必要に応じて array_values() で連番にしています。
金額を税込価格に変換する
$prices = [1000, 2000, 3000];
$taxRate = 1.1;
$pricesWithTax = array_map(fn ($price) => $price * $taxRate, $prices);
print_r($pricesWithTax);
出力は次のようになります。
Array
(
[0] => 1100
[1] => 2200
[2] => 3300
)
アロー関数では外側の $taxRate を自動で使えるため、短く書けます。
バリデーションルールを定義する
$validators = [
'name' => fn ($value) => $value !== '',
'email' => fn ($value) => filter_var($value, FILTER_VALIDATE_EMAIL) !== false,
'age' => fn ($value) => $value >= 20,
];
$data = [
'name' => '田中',
'email' => 'tanaka@example.com',
'age' => 25,
];
foreach ($validators as $field => $validator) {
if (!$validator($data[$field])) {
echo "{$field} が不正です";
}
}
このように、項目ごとのチェック処理を関数として持たせることもできます。
よくある間違い
useを書き忘れる
無名関数で外側の変数を使うときは、use が必要です。
$tax = 1.1;
$calc = function ($price) {
return $price * $tax;
};
このコードでは、無名関数の中で $tax が未定義変数として扱われます。
正しくは次のように書きます。
$tax = 1.1;
$calc = function ($price) use ($tax) {
return $price * $tax;
};
アロー関数なら、use を書かずに外側の変数を使えます。
$tax = 1.1;
$calc = fn ($price) => $price * $tax;
array_mapとarray_filterの引数順を混同する
array_map() と array_filter() は、どちらもコールバックを使いますが、引数の順番が違います。
array_map() は、先にコールバックを書きます。
$result = array_map(fn ($num) => $num * 2, $numbers);
array_filter() は、先に配列を書きます。
$result = array_filter($numbers, fn ($num) => $num % 2 === 0);
この違いは間違えやすいので注意しましょう。
アロー関数で複数文を書こうとする
アロー関数では、複数文をそのまま書くことはできません。
// 誤り
$func = fn ($x) => {
$y = $x * 2;
return $y;
};
複数行の処理を書きたい場合は、無名関数を使います。
$func = function ($x) {
$y = $x * 2;
return $y;
};
array_filterのキー保持を忘れる
array_filter() は、元の配列のキーを保持します。
$numbers = [1, 2, 3, 4];
$result = array_filter($numbers, fn ($num) => $num % 2 === 0);
print_r($result);
結果は次のようになります。
Array
(
[1] => 2
[3] => 4
)
連番の配列にしたい場合は、array_values() を使います。
$result = array_values(
array_filter($numbers, fn ($num) => $num % 2 === 0)
);
PHPのラムダ式を使うときの考え方
短い処理に向いている
ラムダ式は、短い処理をその場で書くのに向いています。
$ids = array_map(fn ($user) => $user['id'], $users);
$activeUsers = array_filter($users, fn ($user) => $user['active']);
このように、処理内容が一目で分かる場合は、ラムダ式を使うとコードが読みやすくなります。
複雑な処理は切り出す
一方で、複雑な条件や長い処理をラムダ式に詰め込むと、読みにくくなります。
$targets = array_filter($users, fn ($user) => $user['age'] >= 20 && $user['status'] === 'active' && $user['email_verified'] && $user['last_login'] >= '2026-01-01');
このような場合は、次のようにメソッド化したほうが分かりやすいです。
function isTargetUser(array $user): bool
{
return $user['age'] >= 20
&& $user['status'] === 'active'
&& $user['email_verified']
&& $user['last_login'] >= '2026-01-01';
}
$targets = array_filter($users, 'isTargetUser');
ラムダ式は便利ですが、コードの読みやすさを優先することが大切です。
まとめ
PHPのラムダ式は無名関数やアロー関数を指す
PHPで「ラムダ式」と呼ばれるものは、主に無名関数やアロー関数です。
無名関数は、名前を持たない関数です。
$double = function ($num) {
return $num * 2;
};
アロー関数は、無名関数を短く書ける構文です。
$double = fn ($num) => $num * 2;
どちらも、配列処理やコールバック処理でよく使われます。
無名関数ではuseを使って外側の変数を取り込む
通常の無名関数では、外側の変数をそのまま使えません。
$tax = 1.1;
$calc = function ($price) use ($tax) {
return $price * $tax;
};
外側の変数を使うには、use を使って明示的に取り込みます。
外側の変数を変更したい場合は、参照渡しを使います。
$count = 0;
$increment = function () use (&$count) {
$count++;
};
アロー関数は短い処理に向いている
アロー関数は、1行で書ける短い処理に向いています。
$names = array_map(fn ($user) => $user['name'], $users);
外側の変数を自動で使えるため、シンプルな配列処理では非常に便利です。
$minAge = 20;
$adults = array_filter($users, fn ($user) => $user['age'] >= $minAge);
ただし、アロー関数は基本的に1つの式を返すための構文です。
複数行の処理や複雑な条件には、無名関数や名前付き関数を使ったほうが読みやすくなります。
実務では使い分けが重要
PHPのラムダ式は、短く書ける便利な構文です。
ただし、何でもラムダ式にすればよいわけではありません。
| 場面 | おすすめ |
|---|---|
| 1行で終わる単純な変換・判定 | アロー関数 |
| 複数行の処理 | 無名関数 |
| 外側の変数を参照渡しで変更したい | 無名関数 |
| ビジネス上の意味がある処理 | 名前付き関数・メソッド |
実務では、次のように考えるとよいです。
短い処理はアロー関数、複数行の処理は無名関数、意味のある処理は名前付き関数やメソッドに切り出す。
この使い分けができると、PHPの配列処理やコールバック処理を、読みやすく保守しやすい形で書けるようになります。
以上、PHPのラムダ式についてでした。
最後までお読みいただき、ありがとうございました。










