laravel5.2 では、HTTP の主な機能は HTTP リクエストをフィルタリングすることです (php aritsan
にはミドルウェア機構がありません)、またシステムレベル (HTTP フィルタリング層) をさらに強化します。クリアでエレガントな使い心地。ただし、ミドルウェアを実装するコードは非常に複雑なので、ミドルウェアのソースコードの内容を分析してみましょう。 php aritsan
是没有中间件机制的),同时也让系统的层次(Http过滤层)更明确,使用起来也很优雅。但实现中间件的代码却很复杂,下面就来具分析下有关中间件的源码的内容。
中间件源码
中间件本身分为两种,一种是所有http的,另一种则是针对route的。一个有中间件的请求周期是:Request得先经过Http中间件,才能进行Router,再经过Requset所对应Route的Route中间件, 最后才会进入相应的Controller代码。laravel把请求分为了两种:http和console。不同的请求方式用它自己的Kernel
来驱动Application
。Http请求则是通过IlluminateFoundationHttpKernel
类来驱动,它定义了所有的中间件,其父类IlluminateFoundationHttpKernel::handle
就是对请求进行处理的入口了
Http中间件
跟踪入口handle()
方法,很容易发现该函数(IlluminateFoundationHttpKernel::sendRequestThroughRouter
):
protected function sendRequestThroughRouter($request) { $this->app->instance('request', $request); Facade::clearResolvedInstance('request'); $this->bootstrap(); return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }
该函数会把Requset分发到Router(通过方法名就知道了), 主要的逻辑则是通过IlluminateRoutingPipeline
完成的, 作用就是让Requset通过Http中间件的检测,然后再到达Router。这里的代码看起来很优雅,但不是很好理解。所以,了解Pipeline
的运行机制就会明白中间件的使用。
Pipeline的运行实现
Pipleline
基类是IlluminatePipelinePipeline
,它的执行在then
方法:
public function then(Closure $destination) { $firstSlice = $this->getInitialSlice($destination); $pipes = array_reverse($this->pipes); return call_user_func( array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable ); }
了解这段代码执行的意图,必须要知道array_reduce()做了什么。 为了清楚array_reduce
怎么运行的,先把array_reduce
重写一次:
//将数组中的元素,依次执行$func函数,且上一次的$func的返回值作为下一次调用$func的第一个参数输入 function array_reduce_back($arr, callable $func, $firstResult = null) { $result = $firstResult; foreach ($arr as $v) { $result = $func($result, $v); } return $result; }
所以,源代码中的$func
是getSlice()
,它返回的是一个回调函数:function($passable) use ($stack, $pipe){...}
($stack
和$pipe
被输入的具体值代替),也就是说作为上一次返回结果输入到下一次$func
的第一个参数是上述的回调函数,如此循环,当数组遍历完成,array_reduce
就返回的是一个回调函数,现在关键就是了解这个回调函数是什么样子,又如何执行?为方便讨论,可分析下面的代码:
call_user_func( array_reduce([1, 2, 3], $this->getSlice(), $firstSlice), $this->passable );
执行说明:
1.$result_0
是初始化的值 ,为$firstSlice
,即是IlluminatePipelinePipeline::getInitialSlice
的返回回调
2.每遍历一个元素,都会执行IlluminatePipelinePipeline::getSlice
的回调,同时也会返回一个回调
3.$result
中的具体执行代码都在getSlice()
中
4.最后的array_reduce
返回结果是$result_3
,是一个有多层闭包的回调函数
5.执行的是call_user_func($result_3, $this->passable)
,即执行function($this->passable) use ($result_2, 3){...}
至此已经清楚了then()
是如何运行的了,要继续下去,则需再搞定回调函数到底怎么执行的.现在再跟着sendRequestThroughRouter
中的Pipeline
走,看它是如何执行的。
// 把具体的参数带进来 return (new Pipeline($this->app)) ->send($request) ->through(['\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode']) ->then($this->dispatchToRouter());
用上面的所分析的Pipeline
执行过程,很快就会分析出最后执行的是
function($requset) use (\Illuminate\Foundation\Http\Kernel::dispatchToRouter(), '\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode') { if ($pipe instanceof Closure) { return call_user_func($pipe, $passable, $stack); } // $name和$parameters很容易得到 // $name = '\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode'; // $parameters = []; list($name, $parameters) = $this->parsePipeString($pipe); // 执行的就是\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::handle($request, \Illuminate\Foundation\Http\Kernel::dispatchToRouter()) return call_user_func_array([$this->container->make($name), $this->method], array_merge([$passable, $stack], $parameters)); }
逻辑处理已经到了IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::handle
,其代码是:
public function handle($request, Closure $next) { if ($this->app->isDownForMaintenance()) { throw new HttpException(503); } return $next($request); }
这里,它处理了这个中间件所需要过滤的条件,同时执行了$next($request)
,即IlluminateFoundationHttpKernel::dispatchToRouter()
, 这样,就把Request转到了Router中,也就完成了Http中间件的所有处理工作,而$next($request)
是每个中间件都不可少的操作,因为在回调中嵌套了回调,就是靠中间件把Request
传递到下一个回调中,也就会解析到下一个中间件,直到最后一个。紧跟上面的已分析的Pipeline
执行过程,讲其补充完整:
6.执行$result_3中的回调,getSlice
实例化中间件,执行其handle
,在中间件处理中执行回调
7.回调中还嵌套回调的,每个中间件中都需有执行回调的代码$next($request)
ミドルウェアのソース コード
ミドルウェア自体は 2 つのタイプに分かれており、1 つはすべて http 用で、もう 1 つはルート用です。 。ミドルウェアを使用したリクエスト サイクルは次のとおりです。リクエストはルーターに送信される前に、まず 🎜HTTP ミドルウェアを通過し、次に、 に対応するルートの🎜Route ミドルウェアを通過する必要があります。 Requset >、最後に対応する🎜コントローラー コードが入力されます。 Laravel はリクエストを http と console の 2 つのタイプに分類します。さまざまなリクエスト メソッドは、独自のKernel
を使用して Application
を駆動します。 HTTP リクエストは、すべてのミドルウェアを定義する IlluminateFoundationHttpKernel
クラスによって駆動され、その親クラス IlluminateFoundationHttpKernel::handle
がリクエストを処理するためのエントリ ポイントです 🎜HTTP ミドルウェア🎜エントリ handle()
メソッドを追跡すると、この関数を簡単に見つけることができます ( IlluminateFoundationHttpKernel::sendRequestThroughRouter): 🎜// 使用管道,发送$request,使之通过middleware ,再到$func (new Pipeline($this->app))->send($request)->through($this->middleware)->then($func);🎜この関数は Requset を Router に配布します (メソッド名でわかります)。メイン ロジックは
IlluminateRoutingPipeline
を通じて完了します。機能は、Requset が Http ミドルウェアの検出を通過させてから Router に到達させることです。このコードはエレガントに見えますが、あまり理解できません。したがって、Pipeline
の動作メカニズムを理解すると、ミドルウェアの使用方法が理解できます。 🎜パイプラインの実行中の実装
🎜Pipleline
基本クラスは IlluminatePipelinePipeline
です。その実行は then
メソッド内で行われます: 🎜public function dispatchToRoute(Request $request) { // 找到具体的路由对象,过程略 $route = $this->findRoute($request); $request->setRouteResolver(function () use ($route) { return $route; }); // 执行Request匹配到Route的事件,具体的代码在这里:\Illuminate\Foundation\Providers\FoundationServiceProvider::configureFormRequests $this->events->fire(new Events\RouteMatched($route, $request)); // 这里就运行路由中间件了 $response = $this->runRouteWithinStack($route, $request); return $this->prepareResponse($request, $response); } protected function runRouteWithinStack(Route $route, Request $request) { // 获取该路由上的中间件 // 简单就点可这样写: // $middleware = App::shouldSkipMiddleware() ? [] : $this->gatherRouteMiddlewares($route); $shouldSkipMiddleware = $this->container->bound('middleware.disable') && $this->container->make('middleware.disable') === true; $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddlewares($route); // 了解Pipeline后,这里就好理解了,应该是通过管道,发送$request,经过$middleware,再到then中的回调 return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(function ($request) use ($route) { return $this->prepareResponse( $request, $route->run($request) ); }); }🎜 このコード実行の意図を理解するには、array_reduce() が何をするのかを知る必要があります。
array_reduce
がどのように動作するかを理解するには、まず array_reduce
を書き換えます。 🎜rrreee🎜 つまり、ソース コードの $func
は getSlice( )
、コールバック関数を返します: function($passable) use ($stack, $pipe){...}
($stack
and $pipe
は入力された特定の値に置き換えられます)、つまり、最後の戻り結果として次の $func
に入力される最初のパラメーターは上記のコールバック関数です。配列の走査が完了すると、array_reduce
はコールバック関数を返します。ここで重要なのは、このコールバック関数がどのようなもので、どのように実行されるかを理解することです。議論を容易にするために、次のコードを分析できます: 🎜rrreee🎜
1.
$result_0
は初期化された値であり、$firstSlice
であり、IlluminatePipelinePipeline::getInitialSlice
の戻りコールバックです。 >/>2. 要素が走査されるたびに、
IlluminatePipelinePipeline::getSlice
のコールバックが実行され、コールバックも返されます。3. 特定の実行。
$result
内 コードはすべて getSlice()
4 にあります。最終的な
array_reduce
の戻り結果は $result_3 (多層クロージャ) コールバック関数
5. 実行は call_user_func($result_3, $this->passable)
、つまり function($this->passable) use ($result_2 , 3){...}
🎜🎜 これで、then()
がどのように動作するかが明確になりました。続けて、コールバック関数がどのように実行されるかを理解する必要があります。次に、sendRequestThroughRouter
の Pipeline
に従って、その実行方法を確認します。 🎜rrreee🎜上で分析した Pipeline
実行プロセスを使用すると、最後の実行が 🎜rrreee🎜 であることがすぐに分析されます。論理処理は、次の IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::handle
に到着しました。コードは次のとおりです: 🎜rrreee🎜 ここでは、このミドルウェアで必要なフィルタリング条件を処理し、$next($request)
、つまり IlluminateFoundationHttpKernel::dispatchToRouter()
を実行します。 >, このようにして、Request が Router に転送され、Http ミドルウェアのすべての処理作業が完了します。$next($request)
は、すべてのミドルウェアにとって必須の操作です。 callback はコールバック内にネストされています。これは、ミドルウェアが Request
を次のコールバックに渡し、最後のコールバックまで次のミドルウェアで解析されることを意味します。上記で分析した Pipeline
実行プロセスに従って、それを完全に説明します。 🎜🎜6. $result_3 でコールバックを実行し、getSlice
でミドルウェアをインスタンス化し、その handle、ミドルウェア処理でコールバックを実行します🎜🎜7. コールバックはコールバックにもネストされており、各ミドルウェアにはコールバック $next($request) code> を実行するコードが必要です。コールバックが実行される順序は 3::handel、2::handel、1::handel、$first🎜 です。<p>8.最里面一层,一定是传递给then()的参数,then执行的就是最后一步</p>
<p>9.执行的顺序是由数组中的最后一个,向前,到then()的参数,为了使其执行顺序是数组中的第一个到最后一个,再到then()中的参数,then()方法中就做了一个反转<code>array_reverse
Pipeline小结
现在,Pipeline的所有执行流程就都分析完了。实现代码真的很绕,但理解之后编写自定义的中间件应该就很容易了。现在再把Pipeline
的使用翻译成汉语,应该是这样的
// 使用管道,发送$request,使之通过middleware ,再到$func (new Pipeline($this->app))->send($request)->through($this->middleware)->then($func);
这样的代码不管是从语义上,还是使用上都很优雅,高!确实是高!再回到源码,Requset的流程就通过dispatchToRouter
进入到了Router
Route中间件
在Router中,\Illuminate\Routing\Router::dispatch
就承接了来自Http中间件的Requset, Router把Request分发到了具体的Route,再进行处理,主要代码如下:
public function dispatchToRoute(Request $request) { // 找到具体的路由对象,过程略 $route = $this->findRoute($request); $request->setRouteResolver(function () use ($route) { return $route; }); // 执行Request匹配到Route的事件,具体的代码在这里:\Illuminate\Foundation\Providers\FoundationServiceProvider::configureFormRequests $this->events->fire(new Events\RouteMatched($route, $request)); // 这里就运行路由中间件了 $response = $this->runRouteWithinStack($route, $request); return $this->prepareResponse($request, $response); } protected function runRouteWithinStack(Route $route, Request $request) { // 获取该路由上的中间件 // 简单就点可这样写: // $middleware = App::shouldSkipMiddleware() ? [] : $this->gatherRouteMiddlewares($route); $shouldSkipMiddleware = $this->container->bound('middleware.disable') && $this->container->make('middleware.disable') === true; $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddlewares($route); // 了解Pipeline后,这里就好理解了,应该是通过管道,发送$request,经过$middleware,再到then中的回调 return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(function ($request) use ($route) { return $this->prepareResponse( $request, $route->run($request) ); }); }
如何获取Route中间件的,就可以跟gatherRouteMiddlewares
,这个代码并不难,很好跟。接下来,Request就到到达至于Controller, Request是如何到达Controller的代码就不难了,这里就不说了
Controller后执行中间件
成功获取Response后,在public/index.php
58行执行了$kernel->terminate($request, $response);
, 也就是在主要逻辑处理完成之后,再执行此代码,它实际上调用是的\Illuminate\Foundation\Http\Kernel::terminate
, 跟进去就很容易发现,它处理了这此请求所涉及到的中间件,并执行了各自的terminate
方法,到这里,中间件的另一个功能就展现出来了,就是主要逻辑完成之后的收尾工作.到这里为止,中间件就完成了它的使命(一个请求也就完成了)
如何使用中间件
在官方文档上讲解的很清楚注册中间
中间件小结
至此,中间件的实现逻辑与使用就清晰了.从执行的顺序来分,一个在Controller
之前,一个在Controller
之后,所以它一个很重要的作用就是可以让Controller
专注于自己的主要逻辑的职责更明确. 奇怪的是,但前后两种中间件的执行方式却不一样, \Illuminate\Foundation\Http\Kernel::terminate
,中间件的结束却没有使用Pipeline
, 而是直接foreach
.相同的工作却用两种代码来实现.现在看来,中间件本身并不复杂,但它带给了我两个启发,1.层次明确 2,Pipeline
所带来的优雅.
相关推荐:
Laravel 5.1框架中如何创建自定义Artisan控制台命令
以上がlaravel5.2をベースとしたミドルウェアのソースコード解析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

Laravelは、次のようなWeb開発プロセスを最適化します。1。ルーティングシステムを使用してURL構造を管理します。 2。ブレードテンプレートエンジンを使用して、ビュー開発を簡素化します。 3.キューを介して時間のかかるタスクを処理します。 4. Eloquentormを使用して、データベース操作を簡素化します。 5.ベストプラクティスに従って、コードの品質と保守性を向上させます。

Laravelは、強力なツールセットを提供し、開発プロセスを簡素化し、コードの保守性とスケーラビリティを向上させる最新のPHPフレームワークです。 1)Eloquentormはデータベース操作を簡素化します。 2)ブレードテンプレートエンジンは、フロントエンド開発を直感的にします。 3)職人のコマンドラインツールは、開発効率を向上させます。 4)パフォーマンスの最適化には、MVCアーキテクチャ、キューの処理、および書き込みテストケースの使用、キャッシュメカニズムの使用、キャッシュメカニズムの使用が含まれます。

LaravelのMVCアーキテクチャは、データロジック、プレゼンテーション、ビジネス処理の分離のためのモデル、ビュー、およびコントローラーを介して、コードの構造と保守性を向上させます。 1)モデルはデータを処理します。2)ビューは表示の責任があります。3)コントローラーはユーザー入力とビジネスロジックを処理します。このアーキテクチャにより、開発者はビジネスロジックに集中し、コードの泥沼に陥ることを避けることができます。

Laravelは、MVCアーキテクチャに基づいたPHPフレームワークで、簡潔な構文、強力なコマンドラインツール、便利なデータ操作、柔軟なテンプレートエンジンを備えています。 1.エレガントな構文と使いやすいAPIにより、開発が迅速かつ使いやすくなります。 2。職人コマンドラインツールは、コード生成とデータベース管理を簡素化します。 3.Eloquentormは、データ操作を直感的かつシンプルにします。 4.ブレードテンプレートエンジンは、高度なビューロジックをサポートしています。

Laravelは、エレガントな構文、豊富な機能、強力なコミュニティサポートを提供するため、バックエンドサービスの構築に適しています。 1)LaravelはMVCアーキテクチャに基づいており、開発プロセスを簡素化します。 2)Eloquentormが含まれ、データベース操作を最適化します。 3)Laravel's Ecosystemは、開発効率を向上させるために、職人、ブレード、ルーティングシステムなどのツールを提供します。

継続的な技術の進歩のこの時代において、現代のプログラマーにとって高度なフレームワークをマスターすることが重要です。この記事では、Laravelフレームワークであまり知られていないテクニックを共有することで、開発スキルを向上させるのに役立ちます。エレガントな構文と幅広い機能で知られるこの記事では、その強力な機能を掘り下げ、効率的で保守可能なWebアプリケーションを作成するための実用的なヒントとコツを提供します。

LaravelとThinkPhpはどちらも人気のあるPHPフレームワークであり、開発における独自の利点と短所を持っています。この記事では、2つの深さを比較し、アーキテクチャ、機能、パフォーマンスの違いを強調して、開発者が特定のプロジェクトのニーズに基づいて情報に基づいた選択を行うのに役立ちます。

Laravelのユーザーログイン機能の構築は重要なタスクであり、この記事では、ユーザー登録からログイン検証までのすべての重要なステップをカバーする包括的な概要を提供します。 Laravelの組み込み検証機能の力に飛び込み、特定のニーズに合わせてログインプロセスをカスタマイズして拡張することをガイドします。これらのステップバイステップの手順に従うことにより、Laravelアプリケーションのユーザーにシームレスなアクセスエクスペリエンスを提供する安全で信頼性の高いログインシステムを作成できます。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

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

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、
