ホームページ PHPフレームワーク Laravel Laravelミドルウェアを作成するためのアイデアの分析

Laravelミドルウェアを作成するためのアイデアの分析

Mar 29, 2020 am 09:07 AM
laravel

laravelのミドルウェアを解析するための実装原則はインターネット上にたくさんありますが、読んでも理解できない読者もいるのではないかと思いますが、作者はarray_reduce関数をどうやって使おうと考えたのでしょうか?

推奨: laravel チュートリアル

この記事は私自身の視点から始まり、私が作成者であればこのミドルウェア関数をどのように実装するか、またその見つけ方と使用方法をシミュレートします。対応する機能。

laravel ミドルウェアとは

Laravel ミドルウェアは、ロジック コードを変更することなく、元のプログラム フローを中断し、ミドルウェアを通じて処理するメカニズムを提供します。機能。たとえば、ロギング ミドルウェアは、ロジック コードを変更せずに、リクエストとレスポンスのログを簡単に記録できます。

次に、ソフトウェアの実行プロセスを簡略化しましょう。コア クラス カーネルがあり、以下はその laravel コードです。

#捕获请求
$request = Illuminate\Http\Request::capture()
#处理请求
$response = $kernel->handle($request);
ログイン後にコピー

コードの機能は、リクエストをキャプチャしてレスポンスを返すことです。 。次に、特定の実行ロジックに配布され、結果を返すコード セグメントを示します。

$kernel->handle() メソッドの実行前または実行後にロジックを追加したい場合、どのように記述すればよいでしょうか?

$request = Illuminate\Http\Request::capture()
function midware(){
    before()#在之前执行的语句集合
    #####    
    $response = $kernel->handle($request);
    #####
    after()#在之后执行的语句集合
}
ログイン後にコピー

このように書くのは明らかに問題ありませんが、スケーラビリティがありません。何かを実行するにはこのメソッドを変更する必要があります。これをコアコンテンツにカプセル化することは不可能です。フレームワーク。改善方法

実行するミドルウェアクラスを定義し、before()とafter()の2つのメソッドを実装します。

#配置项中有一项配置中间件:
middleware = '';
$request = Illuminate\Http\Request::capture()
function midware(){
    middleware.before()
    #####    
    $response = $kernel->handle($request);
    #####
    middleware.after()
}
ログイン後にコピー

問題は解決しますか?変更する必要がないという問題は解決します。しかし、複数のミドルウェアが必要な場合はどうなるでしょうか?最も簡単に考えられるのは、ミドルウェア配列 middleware_arr を定義し、各ミドルウェア クラスを定義することです。コードは次のとおりです:

#配置项中有middleware_arr
middleware_arr=array();
$request = Illuminate\Http\Request::capture()
function midware(){
    foreach(middleware_arr as middleware){
       middleware.before()
    }
    #####    
    $response = $kernel->handle($request);
    #####
    foreach(middleware_arr as middleware){
        middleware.after()
    }
}
ログイン後にコピー

少し古いですが、問題は解決します。しかし、これにはまだ問題があります。つまり、パラメータをミドルウェアにどのように渡すかということです。次のようにしても問題ありません:

$request = Illuminate\Http\Request::capture()
function midware(){
    foreach(middleware_arr as middleware){
       middleware.before($request)
    }
    #####    
    $response = $kernel->handle($request);
    #####
    foreach(middleware_arr as middleware){
        middleware.after($response)
    }
}
ログイン後にコピー

これで問題は解決したように見えますが、注意深く分析すると、次のようになります。指定されるたびに、ミドルウェアはすべて元の $request であることがわかりますが、これは明らかに機能しません。次のように変更します:

$request = Illuminate\Http\Request::capture()
function midware(){
    foreach(middleware_arr as middleware){
       $request = middleware.before($request)
    }
    #####    
    $response = $kernel->handle($request);
    #####
    foreach(middleware_arr as middleware){
        $response = middleware.after($response)
    }
}
ログイン後にコピー

もう 1 つの質問は、2 つのミドルウェア A と B があると仮定すると、何をするかということです。

$request = Illuminate\Http\Request::capture()
$request = A.before($request);
$request = B.before($request);
$response = $kernel->handle($request);
$response = A.after();
$response = B.after();
ログイン後にコピー

これは合理的ですか? 判断するのは簡単ではありません。リクエストとレスポンスのログを記録するミドルウェアがあると仮定します。現時点では、どこに配置しても記録することはできません。最初のリクエストと最後のリクエストのログを完全に記録します。同様の状況で 2 つのクラスを作成する必要がありますか? 1 つはリクエストを記録してミドルウェア配列の最初に配置し、もう 1 つは応答を処理して配列の最後の場所に配置します。要件を満たすように、後続の foreach を実行する前に middleware_arr 配列を反転することをお勧めします:

$request = Illuminate\Http\Request::capture()
$request = A.before($request);
$request = B.before($request);
$response = $kernel->handle($request);
$response = B.after();
$response = A.after();
ログイン後にコピー

しかし、この時代遅れで柔軟性のないソリューションに対して、より良い解決策はないのかと疑問にも思い始めました。この実行シーケンスを観察すると、ラッパー スタイル (オニオン スタイル) であることがわかりました。次の問題に対する、より柔軟で洗練された解決策を見つけることはできますか? 上の構造を見ると、いつも少し見覚えがあるように感じます。A の関数が B の関数をラップし、B の関数には最初の関数が含まれているのとよく似ています。実行コード。関数内で関数を呼び出すことは簡単ですが、ここでの各ミドルウェアは他のミドルウェアの存在を知らないため、他のミドルウェアで実行する関数を上位に渡す必要があります。 array_reduce()、

array_reduce 関数定義:mixed array_reduce ( array $input , callable $function [,mixed $initial = NULL ] )

<?php
 function  rsum ( $v ,  $w )
{
     $v  +=  $w ;
    return  $v ;
}
function  rmul ( $v ,  $w )
{
     $v  *=  $w ;
    return  $v ;
}
 $a  = array( 1 ,  2 ,  3 ,  4 ,  5 );
 $x  = array();
 $b  =  array_reduce ( $a ,  "rsum" );
 $c  =  array_reduce ( $a ,  "rmul" ,  10 );
 ?>   
 #输出:
这将使 $b  的值为 15, $c  的值为 1200(= 10*1*2*3*4*5)
ログイン後にコピー

array_reduce() はコールバックで動作します入力配列内の各セルに対して関数を繰り返し実行することで、配列を単一の値に削減します。複数の関数を 1 つの関数にラップし、最終的に呼び出されます。

#我们先假设只有一个middleware,叫log来简化情况,这里的类应该是一个类全路径,我这里就简单的写一下,要不然太长了。
    $middleware_arr = [&#39;log&#39;];
#最终要执行的代码先封装成一个闭包,要不然没有办法传递到内层,如果用函数名传递函数的话,是没有办法传递参数的。
    $default = function() use($request){
        return $kernel->handle($request);
    }
    $callback = array_reduce($middleware_arr,function($stack,$pipe) {
        return function() use($stack,$pipe){
          return $pipe::handle($stack);
        };
    },$default);
    
    
# 这里 callback最终是 这样一个函数:
    function() use($default,$log){
          return $log::handle($default);
        };
        
#所以每一个中间件都需要有一个方法handle方法,方法中要对传输的函数进行运行,类似如下,这里我类名就不大写了
    class log implements Milldeware {
        public static function handle(Closure $func)
        {
            $func();
        }
    }
    
#这里不难看出可以加入中间件自身逻辑如下:
 class log implements Milldeware {
        public static function handle(Closure $func)
        {
            #这里可以运行逻辑块before()
            $func();
            #这里可以运行逻辑块after()
        }
    }
ログイン後にコピー

このように、コールバック関数を実行するときの実行順序は次のとおりです。

最初に log::haddle() メソッドを実行し、

ログを実行します::before() メソッド

デフォルトのメソッドを実行し、$kernel->handle($request)を実行します

log::after() メソッドを実行します

次に次のように複数の状況をシミュレートします:

    $middleware_arr = [&#39;csrf&#39;,&#39;log&#39;];
#最终要执行的代码先封装成一个闭包,要不然没有办法传递到内层,如果用函数名传递函数的话,是没有办法传递参数的。
    $default = function() use($request){
        return $kernel->handle($request);
    }
    $callback = array_reduce($middleware_arr,function($stack,$pipe) {
        return function() use($stack,$pipe){
          return $pipe::handle($stack);
        };
    },$default);
    
    
# 这里 callback最终是 执行这样:
    $log::handle(function() use($default,$csrf){
                    return $csrf::handle($default);
                });
ログイン後にコピー

実行シーケンスは次のとおりです:

1. 最初に log::haddle (csrf::handle クロージャー関数を含む) メソッド

# を実行します。 ##2. log::before () メソッドを実行します。

3. クロージャを実行すると、$csrf::handle($default) が実行されます。

4. csrf::before() を実行します。 method

5. デフォルトのメソッドを実行し、$kernel->handle($request)

6. csrf::after() メソッドを実行します

7。 log::after() メソッドを実行します

ここでのもう 1 つの問題は、ミドルウェアによって生成された結果が転送されないことです。共有リソースを変更することで同じ目的を達成できます。実際に実行する必要はありません。値を次のミドルウェアに渡します。

これでこのドキュメントは終わりですが、実際には、この記事を書いたときに初めて判明した関節も多くあります。特に、クロージャ関数の使い方と理解が深まりました。クロージャ関数はリソースの使用を遅らせる可能性があります。たとえば、現時点で実行に適していないステートメントを後で渡す必要があります。クロージャは使用できます。これは、従来の関数では実行できないことです。

以上がLaravelミドルウェアを作成するためのアイデアの分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHP でオブジェクト リレーショナル マッピング (ORM) を使用してデータベース操作を簡素化するにはどうすればよいですか? PHP でオブジェクト リレーショナル マッピング (ORM) を使用してデータベース操作を簡素化するにはどうすればよいですか? May 07, 2024 am 08:39 AM

PHP でのデータベース操作は、オブジェクトをリレーショナル データベースにマップする ORM を使用して簡素化されます。 Laravel の EloquentORM を使用すると、オブジェクト指向構文を使用してデータベースと対話できます。モデル クラスを定義したり、Eloquent メソッドを使用したり、実際にブログ システムを構築したりすることで ORM を使用できます。

PHP単体テストツールの長所と短所の分析 PHP単体テストツールの長所と短所の分析 May 06, 2024 pm 10:51 PM

PHP 単体テスト ツール分析: PHPUnit: 大規模プロジェクトに適しており、包括的な機能を提供し、インストールが簡単ですが、冗長で遅い場合があります。 PHPUnitWrapper: 小規模プロジェクトに適しており、使いやすく、Lumen/Laravel に最適化されていますが、機能が限られており、コード カバレッジ分析は提供されず、コミュニティ サポートも限られています。

Laravel と CodeIgniter の最新バージョンの比較 Laravel と CodeIgniter の最新バージョンの比較 Jun 05, 2024 pm 05:29 PM

Laravel 9 と CodeIgniter 4 の最新バージョンでは、更新された機能と改善が提供されます。 Laravel9はMVCアーキテクチャを採用しており、データベース移行、認証、テンプレートエンジンなどの機能を提供します。 CodeIgniter4 は、HMVC アーキテクチャを使用してルーティング、ORM、およびキャッシュを提供します。パフォーマンスの面では、Laravel9 のサービスプロバイダーベースの設計パターンと CodeIgniter4 の軽量フレームワークにより、優れたパフォーマンスが得られます。実際のアプリケーションでは、Laravel9 は柔軟性と強力な機能を必要とする複雑なプロジェクトに適しており、CodeIgniter4 は迅速な開発や小規模なアプリケーションに適しています。

Laravel - アーティザンコマンド Laravel - アーティザンコマンド Aug 27, 2024 am 10:51 AM

Laravel - アーティザン コマンド - Laravel 5.7 には、新しいコマンドを処理およびテストするための新しい方法が付属しています。これには職人コマンドをテストする新しい機能が含まれており、そのデモについては以下で説明します。

Laravel と CodeIgniter のデータ処理機能はどのように比較されますか? Laravel と CodeIgniter のデータ処理機能はどのように比較されますか? Jun 01, 2024 pm 01:34 PM

Laravel と CodeIgniter のデータ処理機能を比較します。 ORM: Laravel はクラスとオブジェクトのリレーショナル マッピングを提供する EloquentORM を使用しますが、CodeIgniter は ActiveRecord を使用してデータベース モデルを PHP クラスのサブクラスとして表します。クエリビルダー: Laravel には柔軟なチェーンクエリ API がありますが、CodeIgniter のクエリビルダーはよりシンプルで配列ベースです。データ検証: Laravel はカスタム検証ルールをサポートする Validator クラスを提供しますが、CodeIgniter には組み込みの検証関数が少なく、カスタム ルールの手動コーディングが必要です。実践例:ユーザー登録例はLarを示しています

Laravel と CodeIgniter: 大規模プロジェクトにはどちらのフレームワークが適していますか? Laravel と CodeIgniter: 大規模プロジェクトにはどちらのフレームワークが適していますか? Jun 04, 2024 am 09:09 AM

大規模プロジェクト用のフレームワークを選択する場合、Laravel と CodeIgniter にはそれぞれ独自の利点があります。 Laravel はエンタープライズレベルのアプリケーション向けに設計されており、モジュール設計、依存関係の注入、強力な機能セットを提供します。 CodeIgniter は、速度と使いやすさを重視した、小規模から中規模のプロジェクトに適した軽量フレームワークです。複雑な要件と多数のユーザーを伴う大規模なプロジェクトには、Laravel のパワーとスケーラビリティがより適しています。単純なプロジェクトやリソースが限られている状況では、CodeIgniter の軽量で迅速な開発機能がより理想的です。

Laravel と CodeIgniter ではどちらが初心者に優しいでしょうか? Laravel と CodeIgniter ではどちらが初心者に優しいでしょうか? Jun 05, 2024 pm 07:50 PM

初心者にとって、CodeIgniter は学習曲線が緩やかで機能は少ないですが、基本的なニーズはカバーしています。 Laravel は幅広い機能セットを提供しますが、学習曲線はわずかに急になります。パフォーマンスの点では、Laravel と CodeIgniter はどちらも良好なパフォーマンスを示します。 Laravel にはより広範なドキュメントとアクティブなコミュニティ サポートがあり、CodeIgniter はよりシンプルで軽量で、強力なセキュリティ機能を備えています。ブログアプリケーションを構築する実際のケースでは、Laravel の EloquentORM を使用するとデータ操作が簡素化されますが、CodeIgniter ではより手動の構成が必要になります。

PHPコードの単体テストと統合テスト PHPコードの単体テストと統合テスト May 07, 2024 am 08:00 AM

PHP 単体テストおよび統合テスト ガイド 単体テスト: コードまたは関数の単一単位に焦点を当て、PHPUnit を使用して検証用のテスト ケース クラスを作成します。統合テスト: 複数のコードユニットがどのように連携するかに注意し、PHPUnit の setUp() メソッドと TearDown() メソッドを使用してテスト環境をセットアップおよびクリーンアップします。実際のケース: PHPUnit を使用して、データベースの作成、サーバーの起動、テストコードの作成など、Laravel アプリケーションの単体テストと統合テストを実行します。

See all articles