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

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 サイトの他の関連記事を参照してください。

声明
この記事はcnblogsで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
タスク管理ツール:リモートプロジェクトの進捗状況の優先順位付けと追跡タスク管理ツール:リモートプロジェクトの進捗状況の優先順位付けと追跡May 02, 2025 am 12:25 AM

Taskmanagementtoolsareessentialforeffectiveremoteprojectmanagementbyprioritizingtasksandtrackingprogress.1)UsetoolslikeTrelloandAsanatosetprioritieswithlabelsortags.2)EmploytoolslikeJiraandMonday.comforvisualtrackingwithGanttchartsandprogressbars.3)K

最新のLaravelバージョンはパフォーマンスをどのように改善しますか?最新のLaravelバージョンはパフォーマンスをどのように改善しますか?May 02, 2025 am 12:24 AM

laravel10EnhancesperformAnceTheveralkeyfeatures.1)ItintroduceSquerybuilderCachinucedatedatabaseload.2)itoptimizeseLoquentModelloadingwithlazingproxies.3)itimprovesRoutingWithineSystem.4)itemproveStingwithingingSystem.4)

フルスタックのLaravelアプリケーションの展開戦略フルスタックのLaravelアプリケーションの展開戦略May 02, 2025 am 12:22 AM

最高のフルスタックのLaravelアプリケーション展開戦略には、1。Zeroダウンタイム展開、2。ブルーグリーン展開、3。連続展開、4。Canaryリリースが含まれます。 1.ゼロダウンタイムデプロイメントは、EnvoyまたはDeployerを使用して展開プロセスを自動化して、更新時にアプリケーションを利用できるようにします。 2。ブルーとグリーンの展開により、2つの環境を維持し、迅速なロールバックを可能にすることにより、ダウンタイムの展開が可能になります。 3.継続的な展開GithubactionsまたはGitlabci/CDを使用して、展開プロセス全体を自動化します。 4。nginx構成を通じてカナリーがリリースされ、パフォーマンスの最適化と迅速なロールバックを確保するために、新しいバージョンをユーザーに徐々に宣伝します。

フルスタックのLaravelアプリケーションのスケーリング:ベストプラクティスとテクニックフルスタックのLaravelアプリケーションのスケーリング:ベストプラクティスとテクニックMay 02, 2025 am 12:22 AM

ToscalealAravelApplicationively、Focusondatabasesharding、Caching、Loadbalancing、andMicroservices.1)databaseShardingTodistributedataacrossMultipledatabase.2)uselaraval'scachingsmultedistestemedisemememememememedtededatedatab

静かな闘争:分散型チームのコミュニケーションの障壁を克服します静かな闘争:分散型チームのコミュニケーションの障壁を克服しますMay 02, 2025 am 12:20 AM

ToovercomcomcommunicationbarriersindistributedTeams、使用:1)VideoCallsForface-to-faceInteraction、2)setClearResponsetimeExpectations、3)ChooseaprateCommunicationSoools、4)CreateAmCommunicationGuide、and5)

フルスタックプロジェクトでのフロントエンドテンプレートにLaravel Bladeを使用しますフルスタックプロジェクトでのフロントエンドテンプレートにLaravel Bladeを使用しますMay 01, 2025 am 12:24 AM

laravelbladeEnhancesFrontendTemplatinginfull stackprojectsbyofferingcleansyntaxandpowerfulfeatures.1)itallows foreasyvariabledisplayandcontrolstructures.2)bladeSupportscreating andReusing components、

Laravelを使用したフルスタックアプリケーションの構築:実用的なチュートリアルLaravelを使用したフルスタックアプリケーションの構築:実用的なチュートリアルMay 01, 2025 am 12:23 AM

laravelisidealforfull-stackapplicationsduetoitseLegantyntax、包括的なセコスシステム、およびパワーフルフィーチュア

リモートロールが接続を維持するためにどのようなツールを使用しましたか?リモートロールが接続を維持するためにどのようなツールを使用しましたか?May 01, 2025 am 12:21 AM

forRemotework、iusezoomforvideocalls、slackformessaging、trelloforprojectmanagement、andgithubforcodecollaboration.1)zoomisReliaible forlargemeetingsbuthefreeversion.2)slackintegrateswellwithtoolSotoolsotification -ortificationoverload.3)trel

See all articles

ホット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衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 Mac版

SublimeText3 Mac版

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

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

SublimeText3 中国語版

SublimeText3 中国語版

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

Dreamweaver Mac版

Dreamweaver Mac版

ビジュアル Web 開発ツール