【PHP8.x】__invokeメソッドの使い方

__invokeメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

__invokeメソッドは、PHPのClosureクラスに属し、オブジェクトを関数のように呼び出すことを可能にするメソッドです。このメソッドは、クラスのインスタンスがまるで関数であるかのように括弧()を付けて呼び出されたときに、PHPの内部で自動的に実行される「マジックメソッド」の一つです。

特にClosureクラスの場合、匿名関数(クロージャ)を変数に代入し、その変数を関数のように呼び出す際に、この__invokeメソッドが内部的に使用されます。例えば、$myClosure = function() { /* 処理 */ };と定義された匿名関数を$myClosure();のように実行すると、PHPは$myClosureオブジェクトの__invokeメソッドを呼び出し、その中に定義された処理を実行します。

これにより、オブジェクトが特定のタスクを実行するためのエントリポイントとして機能し、コードの柔軟性が高まります。開発者がClosureクラスに対して__invokeメソッドを明示的に定義することは通常ありませんが、匿名関数がどのように動作するかを理解する上で重要な概念です。この機能によって、PHPでは関数とオブジェクトの境界がより柔軟になり、より表現力豊かなコードを書くことが可能になります。

構文(syntax)

1<?php
2
3$closureInstance = function (string $param1, int $param2): string {
4    return "Received: " . $param1 . " and " . $param2;
5};
6
7$closureInstance("hello", 123);

引数(parameters)

mixed ...$args

  • mixed ...$args: クロージャが呼び出された際に渡される、任意の数の引数

戻り値(return)

mixed

このメソッドは、クロージャオブジェクトが関数のように呼び出された際に実行され、そのクロージャ内に定義された処理の結果を返します。

サンプルコード

PHP Closure::__invoke の使い所

1<?php
2
3/**
4 * Closure::__invoke の使い所を示すサンプルコード。
5 *
6 * PHPにおいて、無名関数(クロージャ)は内部的に`Closure`クラスのインスタンスです。
7 * この`Closure`インスタンスを変数に代入し、その変数を関数のように呼び出す際、
8 * 内部的に`Closure`クラスの`__invoke`マジックメソッドが実行されます。
9 * これにより、オブジェクトがまるで関数であるかのように振る舞うことができます。
10 */
11
12/**
13 * 渡された引数を結合し、指定された挨拶を前置するクロージャを生成します。
14 *
15 * @param string $greeting クロージャが返す文字列の接頭辞として使う挨拶。
16 * @return Closure 複数の引数を受け取り、それらを結合して返すクロージャ。
17 */
18function createGreeter(string $greeting): Closure
19{
20    // 無名関数(クロージャ)を定義し、返します。
21    // このクロージャは、任意の数の引数を受け取ることができます (`mixed ...$args`)。
22    // このクロージャが呼び出されたとき、PHPの内部でClosure::__invoke()が実行されます。
23    return function (mixed ...$args) use ($greeting): string {
24        // 受け取った引数を文字列に変換し、カンマとスペースで結合します。
25        // array_mapと無名関数で各引数を文字列にキャストしています。
26        $combinedArgs = implode(', ', array_map(fn($arg) => (string)$arg, $args));
27        
28        // 挨拶と結合された引数を返します。
29        return $greeting . ': ' . $combinedArgs;
30    };
31}
32
33// createGreeter関数を呼び出して、挨拶の機能を内包したクロージャ(Closureインスタンス)を取得します。
34$sayHello = createGreeter("こんにちは");
35
36// $sayHelloは`Closure`インスタンスですが、関数のように直接呼び出すことができます。
37// この呼び出しの際、内部的に $sayHello オブジェクトの Closure::__invoke() メソッドが実行されます。
38echo $sayHello('皆さん', 'PHP', 8) . PHP_EOL; // 出力: こんにちは: 皆さん, PHP, 8
39
40// 別の引数で同じクロージャを呼び出す例。
41echo $sayHello('世界') . PHP_EOL; // 出力: こんにちは: 世界
42
43// 別のGreetingで新しいクロージャを作成する例。
44$sayGoodbye = createGreeter("さようなら");
45echo $sayGoodbye('また明日') . PHP_EOL; // 出力: さようなら: また明日
46
47?>

PHPにおいて、Closure::__invokeメソッドは、無名関数(クロージャ)を関数のように呼び出す際に内部的に実行される特殊なマジックメソッドです。クロージャはPHPの内部ではClosureクラスのインスタンスであり、この__invokeがあることで、オブジェクトがまるで関数であるかのように振る舞うことができます。

サンプルコードでは、createGreeter関数が、指定された挨拶を記憶したクロージャを生成し、返します。この返されるクロージャは、mixed ...$argsとして任意の数の引数を受け取ることができ、それらを文字列に変換して結合し、記憶した挨拶を前置した文字列を返します。これが__invokeメソッドが実際に返す値となります。

例えば、$sayHello = createGreeter("こんにちは"); のようにcreateGreeter関数を呼び出すと、「こんにちは」という挨拶を内包したClosureインスタンスが$sayHello変数に代入されます。その後、echo $sayHello('皆さん', 'PHP', 8); のように$sayHello変数を直接関数として呼び出すと、内部的に$sayHelloオブジェクトのClosure::__invokeメソッドが自動的に実行されます。このとき、クロージャに渡された引数('皆さん', 'PHP', 8)が__invokeメソッドの引数として渡され、クロージャ内で定義された処理(引数を結合し、挨拶を前置する)が実行され、「こんにちは: 皆さん, PHP, 8」という文字列が戻り値として返されます。このように、__invokeメソッドは、クロージャが柔軟に振る舞うための仕組みを提供しています。

PHPで無名関数を変数に代入すると、それはClosureクラスのオブジェクトになります。サンプルコードのようにこのオブジェクトを関数のように直接呼び出す際、PHPの内部で自動的にClosure::__invoke()メソッドが実行されています。これにより、オブジェクトがまるで関数であるかのように振る舞うことができ、柔軟なコールバック処理や状態を保持する関数を実現できます。開発者が明示的に__invoke()を呼び出すことは通常ありません。また、クロージャ内で外部の変数を参照するには、useキーワードを使いuse ($greeting)のように明示的に指定する必要がある点にご注意ください。