最新の PHP 新機能シリーズ (5) -- クロージャと匿名関数

WBOY
リリース: 2016-06-23 13:06:15
オリジナル
1054 人が閲覧しました

1. 概要

クロージャと匿名関数は PHP 5.3.0 で導入されたもので、これら 2 つの機能はすべての PHP 開発者が習得する必要があります。

クロージャは、作成時に周囲の状態をカプセル化する関数を指します。たとえクロージャが配置されている環境が存在しなくても、クロージャ内にカプセル化された状態はまだ存在します。

匿名関数は実際には名前のない関数であり、他の PHP 関数オブジェクトと同様に変数に代入して渡すことができます。ただし、匿名関数は依然として関数であるため、呼び出したりパラメーターを渡したりできるため、関数またはメソッドのコールバックとして適しています。

注: 理論的には、クロージャと匿名関数は異なる概念ですが、PHP ではこれらを同じ概念として扱います (匿名関数は PHP ではクロージャ関数とも呼ばれます)。そのため、以下でクロージャについて言及するときは、それらを指します。逆に。

2. クロージャを作成する

クロージャの作成は非常に簡単です:

<?php$greet = function ($name) {    return sprintf("Hello %s\r\n", $name);};echo $greet('LaravelAcademy.org');
ログイン後にコピー

結果の出力:

Hello LaravelAcademy.org
ログイン後にコピー

クロージャは通常の PHP 関数と非常によく似ています: 一般的に使用される構文は同じで、パラメータも受け入れます。値を返すこともできます。ただし、クロージャには関数名がありません。

注: $greet 変数を呼び出すことができる理由は、この変数の値がクロージャであり、変数名の後に () がある限り、クロージャ オブジェクトが __invoke() マジック メソッドを実装しているためです。 PHP はそれを検索し、__invoke メソッドを呼び出します。

通常、PHP クロージャは関数やメソッドのコールバックとして使用されます。実際、array_map や preg_replace_callback などの多くの PHP 関数は、PHP 匿名関数を使用する絶好の機会です。クロージャは、他の値と同様に、パラメータとして他の PHP 関数に渡すことができることを覚えておいてください:

<?php$numberPlusOne = array_map(function ($number) {    return $number += 1;}, [1, 2, 3]);print_r($numberPlusOne);
ログイン後にコピー

クロージャが出現する前は、そのような機能を実装するには、PHP 開発者は名前付き関数を個別に作成し、この関数を名前で参照することしかできませんでした :

<?phpfunction incrementNumner ($number) {    return $number += 1;}$numberPlusOne = array_map(‘incrementNumber’,  [1, 2, 3]);print_r($numberPlusOne);
ログイン後にコピー

これにより、コールバックの実装が使用場所から分離され、クロージャを使用してコードを実装することがより簡潔になります。

3. 親スコープから変数を継承する

PHP では、クロージャ オブジェクトの bindingTo メソッドを手動で呼び出すか、use キーワードを使用して親スコープの変数とステータスを PHP クロージャにアタッチする必要があります。実際のアプリケーションでは、そのほとんどは use キーワードを使用して実装されます。

キーワードを使用する

実際、クロージャは Laravel フレームワークでも広く使用されています。最も一般的なものはルート定義です:

Route::group(['domain' => '{account}.myapp.com'], function () {    Route::get('user/{id}', function ($account, $id) {        //    });});
ログイン後にコピー

ここでの 2 つの関数はクロージャです。親スコープから変数を継承する使用シナリオは、Model.php (IlluminateDatabaseEloquent) の saveOrFail メソッドなど、Laravel の基礎となるソース コードでも一般的です。

このメソッドの機能は、トランザクションを使用してモデル データを保存することです。ここでは、クロージャを使用して保存された状態を返し、use キーワードを使用して親スコープの $options をクロージャに渡し、このデータにアクセスできるようにします。

さらに、Model クラスの ForceFill メソッドなど、複数の親スコープ変数をクロージャに渡すこともサポートしています。

複数の変数はカンマで区切ることができます。

bindTo メソッド

クロージャはオブジェクトであることを前に述べました。そのため、クロージャ内で $this キーワードを使用してクロージャ オブジェクトの内部状態を取得できます。Pay は役に立ちません。 __invoke magic メソッドと bindingTo メソッドに注意してください。

__invoke の役割については前述しましたが、関数を呼び出してオブジェクトを呼び出そうとすると、__invoke() メソッドが自動的に呼び出されます。

次に、bindTo メソッドを見てみましょう。このメソッドを通じて、クロージャの内部状態を他のオブジェクトにバインドできます。ここでは、bindTo メソッドの 2 番目のパラメータが特に重要です。その機能は、バインドされたクロージャのオブジェクトが属する PHP クラスを指定することにより、クロージャは他の場所からバインドされたクロージャの保護されたオブジェクトとプライベート オブジェクトにアクセスできるようになります。 . メンバー変数。

PHP フレームワークは、ルーティング URL を匿名コールバック関数にマップするために、bindTo メソッドをよく使用することがわかります。フレームワークは、匿名コールバック関数をアプリケーション オブジェクトにバインドし、匿名関数で $this キーワードを使用できるようにします。重要な参照 アプリケーション オブジェクト:

<?phpclass App {    protected $routes = [];    protected $responseStatus = '200 OK';    protected $responseContentType = 'text/html';    protected $responseBody = 'Laravel学院';    public function addRoute($routePath, $routeCallback) {        $this->routes[$routePath] = $routeCallback->bindTo($this, __CLASS__);    }    public function dispatch($currentPath) {        foreach ($this->routes as $routePath => $callback) {            if( $callback === $currentPath) {                $callback();            }        }        header('HTTP/1.1 ' . $this->responseStatus);        header('Content-Type: ' . $this->responseContentType);        header('Content-Length: ' . mb_strlen($this->responseBody));        echo $this->responseBody;    }}
ログイン後にコピー

ここでは、addRoute メソッドに注目する必要があります。このメソッドのパラメータはそれぞれルーティング パスとルーティング コールバックです。ディスパッチ メソッドのパラメータは現在の HTTP リクエストのパスです。一致するルーティング コールバックを呼び出します。 9 行目が重要なポイントです。ルーティング コールバックを現在の App インスタンスにバインドします。これを行うと、コールバック関数で App インスタンスのステータスを処理できます:

$app = new App();$app->addRoute(‘user/nonfu’, function(){    $this->responseContentType = ‘application/json;charset=utf8’;    $this->responseBody = ‘{“name”:”LaravelAcademy"}';});$app->dispatch(‘user/nonfu');
ログイン後にコピー

bindTo メソッドは Larval の下部でも使用されます。詳細については、IlluminateSupportTraitsMacroable の __call メソッドを参照してください:

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート