PHPの無名関数の特徴や使い方について

採用はこちら

PHPの無名関数とは、名前を付けずに定義できる関数のことです。
英語ではAnonymous Functionと呼ばれます。

通常の関数では、次のように関数名を付けて定義します。

function greet($name)
{
    return "こんにちは、{$name}さん";
}

echo greet("田中");

一方、無名関数ではfunctionの後ろに関数名を書きません。

$greet = function ($name) {
    return "こんにちは、{$name}さん";
};

echo $greet("田中");

実行結果は次のとおりです。

こんにちは、田中さん

PHPの無名関数はClosureクラスのオブジェクトとして扱われます。
そのため、関数そのものを変数へ代入したり、別の関数へ引数として渡したりできるのが大きな特徴です。

ただし、厳密には「無名関数」と「Closure」は完全に同じ意味ではありません。
無名関数を定義するとClosureが生成されますが、PHPでは既存のcallableからClosureを生成することもできます。

目次

PHPの無名関数の基本的な書き方

無名関数の基本構文

PHPの無名関数は、基本的に次のように記述します。

function (引数) {
    // 処理
};

実際には、変数へ代入して利用するケースが一般的です。

$hello = function () {
    echo "Hello PHP";
};

$hello();

このコードでは、無名関数を$helloへ代入しています。

その後、

$hello();

と記述することで、通常の関数と同じように実行できます。

無名関数では最後のセミコロンが必要

変数へ無名関数を代入するときは、閉じ波括弧の後ろにセミコロンを記述します。

$hello = function () {
    echo "Hello";
};

通常の名前付き関数では、関数定義の最後にセミコロンは必要ありません。

function hello()
{
    echo "Hello";
}

この違いは初心者が間違えやすいポイントです。

PHPの無名関数の特徴

関数名を付ける必要がない

無名関数の大きな特徴は、関数名を考える必要がないことです。

例えば、配列の値を加工するときだけ必要な処理であれば、専用の関数名を付けずにその場で処理を定義できます。

$numbers = [1, 2, 3, 4, 5];

$result = array_map(function ($number) {
    return $number * 2;
}, $numbers);

print_r($result);

実行結果は次のようになります。

Array
(
    [0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    [4] => 10
)

一度しか使わない処理であれば、名前付き関数を別に定義するよりも、処理の場所をまとめやすくなります。

変数へ代入できる

PHPの無名関数は、値のように変数へ代入できます。

$calculate = function ($a, $b) {
    return $a + $b;
};

echo $calculate(10, 20);

実行結果は次のとおりです。

30

このように変数へ保存した無名関数は、必要なタイミングで何度でも呼び出せます。

別の関数へ引数として渡せる

無名関数は、別の関数へ引数として渡すこともできます。

このように、別の処理へ渡して後から実行される関数は、一般にコールバック関数と呼ばれます。

例えば、array_map()では無名関数をコールバックとして利用できます。

$prices = [100, 200, 300];

$result = array_map(function ($price) {
    return $price * 1.1;
}, $prices);

print_r($result);

この場合、

function ($price) {
    return $price * 1.1;
}

の部分がコールバック関数です。

useを使って外側の変数を利用する方法

通常は外側のローカル変数を直接使えない

PHPの無名関数では、関数の外側で定義したローカル変数を、そのまま内部から参照することはできません。

例えば次のように書いても、$messageは無名関数のローカルスコープには存在しません。

$message = "こんにちは";

$greet = function () {
    echo $message;
};

外側の変数を無名関数内で使いたい場合は、useを利用します。

useで変数を取り込む

次のように記述します。

$message = "こんにちは";

$greet = function () use ($message) {
    echo $message;
};

$greet();

実行結果は次のとおりです。

こんにちは

基本構文は次のようになります。

function () use ($変数) {
    // 処理
};

useを利用することで、無名関数を定義した親スコープの変数を取り込めます。

useによる値のキャプチャ

useでは定義時の値が取り込まれる

通常の、

use ($variable)

では、無名関数を定義した時点の値が取り込まれます。

例えば次のコードです。

$message = "こんにちは";

$greet = function () use ($message) {
    echo $message;
};

$message = "こんばんは";

$greet();

実行結果は次のようになります。

こんにちは

無名関数を定義した時点では、$messageの値が「こんにちは」だったためです。

その後、外側の変数を「こんばんは」へ変更しても、すでに取り込まれた値には影響しません。

参照として取り込む場合は&を付ける

外側の変数の変更を無名関数にも反映したい場合は、&を利用して参照として取り込みます。

$message = "こんにちは";

$greet = function () use (&$message) {
    echo $message;
};

$message = "こんばんは";

$greet();

実行結果は次のとおりです。

こんばんは

書き方は次のようになります。

function () use (&$variable) {
    // 処理
};

ただし、参照による変数の共有を多用すると、どこで値が変更されたのか分かりにくくなる場合があります。
必要な場面に限定して使うとよいでしょう。

通常の引数とuseの違い

引数は呼び出し時に値を渡す

通常の引数は、関数を実行するときに値を渡すために使用します。

$greet = function ($name) {
    echo "こんにちは、{$name}さん";
};

$greet("田中");

この場合、$nameには呼び出し時に指定した「田中」が入ります。

useは外側の変数を取り込む

一方、useは無名関数を定義した外側のスコープから変数を取り込むために使用します。

$prefix = "こんにちは";

$greet = function ($name) use ($prefix) {
    echo "{$prefix}、{$name}さん";
};

$greet("田中");

この場合、

  • $nameは関数を呼び出すときに渡す値
  • $prefixは外側のスコープから取り込む値

という違いがあります。

無名関数に引数や戻り値の型を指定する方法

引数を指定できる

無名関数にも通常の関数と同じように引数を指定できます。

$multiply = function ($a, $b) {
    return $a * $b;
};

echo $multiply(5, 10);

実行結果は次のとおりです。

50

型宣言も利用できる

引数型や戻り値型も指定できます。

$multiply = function (int $a, int $b): int {
    return $a * $b;
};

echo $multiply(5, 10);

通常の名前付き関数と同じように型を指定できるため、より安全で意図の分かりやすいコードを書けます。

array_mapで無名関数を使う方法

配列の各要素を加工できる

array_map()は、配列の各要素に対して処理を行う関数です。

無名関数と組み合わせることで、配列の値を簡潔に加工できます。

$numbers = [1, 2, 3, 4, 5];

$result = array_map(function ($number) {
    return $number * 10;
}, $numbers);

print_r($result);

実行結果は次のようになります。

Array
(
    [0] => 10
    [1] => 20
    [2] => 30
    [3] => 40
    [4] => 50
)

名前付き関数を用意することもできますが、その処理を一度しか使わないのであれば無名関数のほうがコードをまとめやすい場合があります。

array_filterで無名関数を使う方法

条件に一致する要素だけを残せる

array_filter()は、条件に一致する要素だけを配列に残す関数です。

例えば偶数だけを取り出す場合は、次のように書けます。

$numbers = [1, 2, 3, 4, 5, 6];

$evenNumbers = array_filter($numbers, function ($number) {
    return $number % 2 === 0;
});

print_r($evenNumbers);

実行結果は次のとおりです。

Array
(
    [1] => 2
    [3] => 4
    [5] => 6
)

array_filter()は元の配列のキーを保持する点に注意してください。

キーを0から振り直したい場合は、array_values()を組み合わせます。

$evenNumbers = array_values(
    array_filter($numbers, function ($number) {
        return $number % 2 === 0;
    })
);

usortで無名関数を使う方法

独自の条件で配列を並び替えられる

usort()では、比較処理を無名関数として指定できます。

$users = [
    ['name' => '田中', 'age' => 30],
    ['name' => '佐藤', 'age' => 20],
    ['name' => '鈴木', 'age' => 40],
];

usort($users, function ($a, $b) {
    return $a['age'] <=> $b['age'];
});

print_r($users);

<=>は宇宙船演算子と呼ばれる比較演算子です。

左側が小さい場合は負の値、等しい場合は0、大きい場合は正の値を返します。

この例では、年齢の小さい順に並び替えられます。

無名関数から無名関数を返す方法

関数を戻り値として利用できる

PHPでは、無名関数そのものを別の関数の戻り値として返すこともできます。

function createMultiplier($multiplier)
{
    return function ($number) use ($multiplier) {
        return $number * $multiplier;
    };
}

$double = createMultiplier(2);
$triple = createMultiplier(3);

echo $double(10);
echo $triple(10);

$doubleには2倍する関数が入り、$tripleには3倍する関数が入ります。

それぞれの無名関数が、作成されたときの$multiplierを保持している点が重要です。

このような仕組みはクロージャの代表的な利用方法の一つです。

クラス内の無名関数で$thisを使う方法

通常の無名関数では$thisを利用できる

オブジェクトのメソッド内で通常の無名関数を定義すると、現在のオブジェクトが自動的にバインドされます。

そのため、無名関数の内部から$thisを使用できます。

class User
{
    private string $name = '田中';

    public function getGreeting(): Closure
    {
        return function () {
            return "こんにちは、{$this->name}さん";
        };
    }
}

$user = new User();

$greet = $user->getGreeting();

echo $greet();

このコードでは、無名関数の内部から$this->nameへアクセスしています。

staticな無名関数とは

staticを付けると$thisが自動バインドされない

無名関数の前にstaticを付けることもできます。

$calculate = static function ($a, $b) {
    return $a + $b;
};

staticな無名関数では、通常の無名関数と異なり$thisが自動的にバインドされません。

例えば次のようになります。

class Example
{
    public function test()
    {
        $func = static function () {
            // $thisは使用できない
        };

        $func();
    }
}

オブジェクトの状態を必要としない処理でstaticを付けると、「この処理は$thisに依存しない」という意図を明確にできます。

PHPの無名関数とアロー関数の違い

アロー関数は短く記述できる

PHP 7.4以降では、fnを使用するアロー関数も利用できます。

通常の無名関数では、次のように書きます。

$rate = 1.1;

$result = array_map(function ($price) use ($rate) {
    return $price * $rate;
}, [100, 200, 300]);

アロー関数では次のように短く記述できます。

$rate = 1.1;

$result = array_map(
    fn($price) => $price * $rate,
    [100, 200, 300]
);

アロー関数は外側の変数を自動的に取り込む

アロー関数では、通常の無名関数のように、

use ($rate)

と書く必要がありません。

外側の変数は自動的に値としてキャプチャされます。

アロー関数は1つの式だけ記述できる

アロー関数では、=>の右側に1つの式を記述します。

そのため、単純な処理には向いています。

$double = fn($number) => $number * 2;

一方、複数の文を順番に実行したい場合は、通常の無名関数を使用します。

$process = function ($value) {
    $value *= 2;
    $value += 10;

    return $value;
};

使い分けの目安としては、

  • 単純な1つの式ならアロー関数
  • 複数の処理が必要なら通常の無名関数

と考えると分かりやすいでしょう。

無名関数と名前付き関数の違い

名前付き関数は再利用する処理に向いている

名前付き関数は次のように定義します。

function calculateTax($price)
{
    return $price * 1.1;
}

複数の場所から何度も利用する共通処理であれば、名前付き関数のほうが用途を理解しやすくなります。

無名関数は一時的な処理に向いている

同じ処理を無名関数で書くと次のようになります。

$calculateTax = function ($price) {
    return $price * 1.1;
};

無名関数は、

  • その場所でしか使用しない処理
  • コールバック処理
  • 配列操作
  • 一時的な処理
  • 外側の変数を保持したい処理

などに向いています。

名前付き関数と無名関数のどちらが優れているというわけではありません。
用途に合わせて使い分けることが大切です。

PHPの無名関数を使うメリット

コールバックをその場で記述できる

無名関数を利用すると、コールバック処理を利用する場所へ直接記述できます。

$result = array_map(function ($value) {
    return $value * 2;
}, $values);

処理内容と使用場所が近いため、コードの流れを理解しやすくなる場合があります。

不要な関数名を増やさずに済む

一度しか使わない処理のために、わざわざ専用の関数名を考える必要がありません。

小さなコールバック処理では特に便利です。

外側の値を保持できる

useを使用すれば、無名関数を作成した時点の値を保持できます。

$taxRate = 1.1;

$calculateTax = function ($price) use ($taxRate) {
    return $price * $taxRate;
};

このように外側の状態を保持できることは、クロージャの重要な特徴です。

PHPの無名関数を使う際の注意点

useの値と参照を混同しない

次の2つは動作が異なります。

use ($value)
use (&$value)

use ($value)では値を取り込みます。

一方、use (&$value)では外側の変数への参照を保持します。

参照を利用すると外側の値を書き換えることもできるため、意図せず状態が変化しないよう注意が必要です。

複雑な処理を無名関数へ詰め込みすぎない

無名関数は便利ですが、長い処理をすべてその場へ記述すると読みづらくなる場合があります。

例えば、

array_map(function ($item) {
    // 数十行にわたる複雑な処理
}, $items);

のようになっている場合は、名前付き関数やクラスのメソッドへ分離したほうが保守しやすいことがあります。

Closureは通常の方法ではシリアライズできない

PHP標準のserialize()を使って、Closureオブジェクトをそのまま通常の方法でシリアライズすることはできません。

そのため、無名関数そのものをセッションや永続データとして保存する用途には向いていません。

外部ライブラリなどによって別の仕組みが提供される場合もありますが、PHP標準のClosureは通常のシリアライズ対象にはできないと理解しておくとよいでしょう。

第一級callable構文と無名関数の関係

PHPでは既存の関数からClosureを生成できる

PHP 8.1以降では、第一級callable構文を利用できます。

例えば次の関数があるとします。

function double(int $value): int
{
    return $value * 2;
}

次のように記述すると、既存の関数からClosureを取得できます。

$func = double(...);

echo $func(10);

この場合、$funcはClosureとして扱われます。

この仕組みがあるため、厳密には「Closureはすべて無名関数である」とはいえません。

無名関数を定義するとClosureが生成されますが、Closureは既存のcallableからも生成できます。

create_functionは現在使用できない

古いPHPの記事ではcreate_functionが登場することがある

古いPHPのサンプルコードでは、create_function()を利用している場合があります。

しかし、create_function()はPHP 7.2で非推奨となり、PHP 8.0で削除されています。

そのため、現在のPHPでは使用しないでください。

古いコードで、

create_function(...)

を見つけた場合は、基本的に現在の無名関数である、

function () {
    // 処理
}

の形式へ書き換えることを検討します。

PHPの無名関数が適している場面

配列の加工や絞り込み

無名関数は、PHPの配列関数と特に相性があります。

例えば、

  • array_map()で要素を加工する
  • array_filter()で要素を絞り込む
  • usort()で独自条件による並び替えを行う

といった場面です。

コールバック処理

処理そのものを別の関数へ渡したい場合にも無名関数が適しています。

フレームワークやライブラリを利用すると、イベント処理やルーティング処理などで無名関数を見る機会も増えます。

一時的な処理

一度だけ必要な小さな処理であれば、名前付き関数を作るより無名関数のほうが簡潔に書ける場合があります。

外側の値を保持したい処理

useを活用すれば、無名関数を作成した時点の値を保持できます。

特定の設定値や条件を保持した関数を作る場合にも便利です。

PHPの無名関数についてよくある疑問

無名関数とクロージャは同じですか

PHPでは無名関数をクロージャと呼ぶことが多く、無名関数を定義するとClosureオブジェクトが生成されます。

ただし、厳密にはClosureは無名関数だけから生成されるものではありません。

第一級callable構文などによって、既存の関数やメソッドからClosureを生成することもできます。

無名関数は何度でも実行できますか

変数へ保存していれば、何度でも実行できます。

$hello = function () {
    echo "Hello\n";
};

$hello();
$hello();
$hello();

無名関数から値を返せますか

通常の関数と同じようにreturnを利用できます。

$add = function ($a, $b) {
    return $a + $b;
};

$result = $add(10, 20);

echo $result;

無名関数に型指定はできますか

可能です。

$add = function (int $a, int $b): int {
    return $a + $b;
};

引数型と戻り値型を明示することで、処理の意図が伝わりやすくなります。

無名関数とアロー関数はどちらを使うべきですか

処理が単純な1つの式であれば、アロー関数を利用すると簡潔に書けます。

$double = fn($value) => $value * 2;

一方、複数の文を実行する場合や、処理が複雑になる場合は通常の無名関数が適しています。

まとめ

PHPの無名関数は、名前を付けずに定義できる関数です。

基本的には次のように記述します。

$func = function ($value) {
    return $value * 2;
};

そして、

echo $func(10);

のように変数を関数として呼び出せます。

無名関数には、変数へ代入できる、コールバックとして渡せる、useによって外側の変数を取り込めるといった特徴があります。

特に、

function () use ($value) {
    // 処理
}

と記述すると、親スコープの値をキャプチャできます。

また、

function () use (&$value) {
    // 処理
}

とすれば、変数を参照として取り込むことも可能です。

PHPでは、array_map()array_filter()usort()などの配列関数をはじめ、さまざまなコールバック処理で無名関数が利用されています。

単純な1つの式ならアロー関数、複数の処理を行うなら通常の無名関数、複数の場所から何度も使う共通処理なら名前付き関数やメソッドというように使い分けると、読みやすく保守しやすいPHPコードを書きやすくなります。

以上、PHPの無名関数の特徴や使い方についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次