Table des matières
Code source du middleware" >Code source du middleware
Pipeline小结" >Pipeline小结
Route中间件" >Route中间件
Controller后执行中间件" >Controller后执行中间件
如何使用中间件" >如何使用中间件
中间件小结" >中间件小结
Maison cadre php Laravel Analyse du code source du middleware basé sur laravel5.2

Analyse du code source du middleware basé sur laravel5.2

Jul 31, 2018 pm 02:37 PM

Dans laravel5.2, la fonction principale de Http est de filtrer les requêtes Http (php aritsan n'a pas de mécanisme middleware) Cela rend également le niveau du système (couche de filtrage Http) plus clair. a l'air élégant aussi. Cependant, le code pour implémenter le middleware est très compliqué. Analysons le contenu du code source du middleware.

Code source du middleware

Le middleware lui-même est divisé en deux types, l'un pour tout http et l'autre pour la route. Un cycle de requête avec middleware est le suivant : La requête doit d'abord passer par le Middleware HTTP avant de pouvoir aller au routeur, puis passer par le Middleware de route, et enfin le Code contrôleur correspondant sera saisi. Laravel divise les requêtes en deux types : http et console. Différentes méthodes de requête utilisent son propre pour conduire Kernel. Les requêtes HTTP sont pilotées par la classe Application
, qui définit tous les middlewares. Sa classe parent IlluminateFoundationHttpKernel est le point d'entrée pour le traitement des requêtes IlluminateFoundationHttpKernel::handle

Middleware HTTP<.>En traçant la méthode d'entrée

, il est facile de trouver la fonction (

) : handle()IlluminateFoundationHttpKernel::sendRequestThroughRouter

Cette fonction distribuera Requset au routeur (vous pouvez la connaître par le nom de la méthode) , la logique principale est complétée via
protected function sendRequestThroughRouter($request)
{
    $this->app->instance(&#39;request&#39;, $request);

    Facade::clearResolvedInstance(&#39;request&#39;);

    $this->bootstrap();

    return (new Pipeline($this->app))
                ->send($request)
                ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                ->then($this->dispatchToRouter());
}
Copier après la connexion
, sa fonction est de laisser le Requset passer la détection du middleware Http, puis d'atteindre le routeur. Le code ici semble élégant mais n'est pas très compréhensible. Par conséquent, si vous comprenez le mécanisme de fonctionnement de

, vous comprendrez l'utilisation du middleware. IlluminateRoutingPipelinePipeline

L'implémentation en cours de Pipeline

la classe de base est

, et son exécution se fait dans la méthode Pipleline : IlluminatePipelinePipelinethen

Pour comprendre le but de cette exécution de code, vous devez savoir ce que fait array_reduce(). Afin de comprendre comment
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
    );
}
Copier après la connexion
fonctionne, réécrivez d'abord

 : array_reducearray_reduce

Donc, le
//将数组中的元素,依次执行$func函数,且上一次的$func的返回值作为下一次调用$func的第一个参数输入
function array_reduce_back($arr, callable $func, $firstResult = null)
{
    $result = $firstResult;
    
    foreach ($arr as $v) {
        $result = $func($result, $v);
    }
    
    return $result;
}
Copier après la connexion
dans le code source est

, et il renvoie une fonction de rappel : $func (getSlice() et function($passable) use ($stack, $pipe){...} sont remplacés par les valeurs spécifiques saisies), c'est-à-dire que le premier paramètre entré dans le $stack suivant comme dernier résultat de retour est la fonction de rappel mentionnée ci-dessus dans cette boucle. , lorsque le tableau est parcouru Une fois terminé, $pipe renverra une fonction de rappel. La clé est maintenant de comprendre à quoi ressemble cette fonction de rappel et comment l'exécuter ? Pour faciliter la discussion, le code suivant peut être analysé : $funcarray_reduce

call_user_func(
        array_reduce([1, 2, 3], $this->getSlice(), $firstSlice), $this->passable
    );
Copier après la connexion

Analyse du code source du middleware basé sur laravel5.2Instructions d'exécution :

1 est la valeur initialisée, qui est

. , c'est-à-dire que c'est le rappel de retour de
$result_02. Chaque fois qu'un élément est traversé, le rappel de $firstSlice sera exécuté, et un rappel IlluminatePipelinePipeline::getInitialSlice3 sera également renvoyé le code d'exécution spécifique. dans
est dans IlluminatePipelinePipeline::getSlice
4. Le résultat final $result est getSlice(), qui est une fonction de rappel de fermeture multicouche
5. Ce qui est exécuté est array_reduce, c'est-à-dire. , $result_3
call_user_func($result_3, $this->passable) est exécuté À ce stade, le fonctionnement de function($this->passable) use ($result_2, 3){...} est clair. Si vous souhaitez continuer, vous devez comprendre comment la fonction de rappel est exécutée. Suivez maintenant

dans.

pour voir comment il est exécuté. then()sendRequestThroughRouterPipelineA l'aide du processus d'exécution

analysé ci-dessus, il sera bientôt analysé que la dernière exécution est
// 把具体的参数带进来
return (new Pipeline($this->app))
                ->send($request)
                ->through([&#39;\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode&#39;])
                ->then($this->dispatchToRouter());
Copier après la connexion

PipelineLe traitement logique a atteint

, et son code C'est :
function($requset) use (\Illuminate\Foundation\Http\Kernel::dispatchToRouter(), &#39;\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode&#39;) {

            if ($pipe instanceof Closure) {
                return call_user_func($pipe, $passable, $stack);
            }
            
            // $name和$parameters很容易得到
            // $name = &#39;\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode&#39;;
            // $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));
}
Copier après la connexion

IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode::handleIci, il traite les conditions de filtrage requises par ce middleware, et en même temps exécute

, c'est-à-dire
public function handle($request, Closure $next)
{
    if ($this->app->isDownForMaintenance()) {
        throw new HttpException(503);
    }

    return $next($request);
}
Copier après la connexion
De cette manière, la Requête est transférée vers. le routeur, et c'est terminé. Tout le travail de traitement du middleware Http est éliminé, et

est une opération indispensable pour tout middleware, car le rappel est imbriqué dans le rappel, ce qui signifie que le middleware passe $next($request) au routeur. prochain rappel, c'est-à-dire sera résolu vers le prochain middleware jusqu'au dernier. Suivez le processus d'exécution IlluminateFoundationHttpKernel::dispatchToRouter() analysé ci-dessus et complétez-le : $next($request)Request6 Exécutez le rappel dans $result_3, Pipeline instanciez le middleware, exécutez son

, dans le middleware Exécutez le rappel pendant le traitement <. 🎜>

7. S'il y a des rappels imbriqués dans le rappel, chaque middleware doit avoir le code pour exécuter le rappel getSlice pour garantir que les rappels dans le rappel seront exécutés. L'ordre d'exécution est 3 :: handel, 2 ::handel, 1 ::handel, $firsthandle

8.最里面一层,一定是传递给then()的参数,then执行的就是最后一步

9.执行的顺序是由数组中的最后一个,向前,到then()的参数,为了使其执行顺序是数组中的第一个到最后一个,再到then()中的参数,then()方法中就做了一个反转array_reverse

Pipeline小结

现在,Pipeline的所有执行流程就都分析完了。实现代码真的很绕,但理解之后编写自定义的中间件应该就很容易了。现在再把Pipeline的使用翻译成汉语,应该是这样的

// 使用管道,发送$request,使之通过middleware ,再到$func
(new Pipeline($this->app))->send($request)->through($this->middleware)->then($func);
Copier après la connexion

这样的代码不管是从语义上,还是使用上都很优雅,高!确实是高!再回到源码,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(&#39;middleware.disable&#39;) &&
                         $this->container->make(&#39;middleware.disable&#39;) === 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)
                        );
                    });
}
Copier après la connexion

如何获取Route中间件的,就可以跟gatherRouteMiddlewares,这个代码并不难,很好跟。接下来,Request就到到达至于Controller, Request是如何到达Controller的代码就不难了,这里就不说了

Controller后执行中间件

成功获取Response后,在public/index.php58行执行了$kernel->terminate($request, $response);, 也就是在主要逻辑处理完成之后,再执行此代码,它实际上调用是的\Illuminate\Foundation\Http\Kernel::terminate, 跟进去就很容易发现,它处理了这此请求所涉及到的中间件,并执行了各自的terminate方法,到这里,中间件的另一个功能就展现出来了,就是主要逻辑完成之后的收尾工作.到这里为止,中间件就完成了它的使命(一个请求也就完成了)

如何使用中间件

在官方文档上讲解的很清楚注册中间

中间件小结

至此,中间件的实现逻辑与使用就清晰了.从执行的顺序来分,一个在Controller之前,一个在Controller之后,所以它一个很重要的作用就是可以让Controller专注于自己的主要逻辑的职责更明确. 奇怪的是,但前后两种中间件的执行方式却不一样, \Illuminate\Foundation\Http\Kernel::terminate,中间件的结束却没有使用Pipeline, 而是直接foreach.相同的工作却用两种代码来实现.现在看来,中间件本身并不复杂,但它带给了我两个启发,1.层次明确 2,Pipeline所带来的优雅.

相关推荐:

laravel5.4中自定义包开发的实例

Laravel 5.1框架中如何创建自定义Artisan控制台命令

laravel框架的启动过程分析

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Quel est le meilleur, Django ou Laravel? Quel est le meilleur, Django ou Laravel? Mar 28, 2025 am 10:41 AM

Django et Laravel sont tous deux des frameworks à pile. Django convient aux développeurs Python et à la logique métier complexe, tandis que Laravel convient aux développeurs PHP et à la syntaxe élégante. 1.Django est basé sur Python et suit la philosophie "Battery-Complete", adaptée au développement rapide et à une grande concurrence. 2.Laravel est basé sur PHP, mettant l'accent sur l'expérience du développeur et convient aux projets de petite et moyenne taille.

Laravel et le backend: alimentation logique d'application Web Laravel et le backend: alimentation logique d'application Web Apr 11, 2025 am 11:29 AM

Comment Laravel joue-t-il un rôle dans la logique backend? Il simplifie et améliore le développement backend par le biais de systèmes de routage, d'éloquente, d'authentification et d'autorisation, d'événements et d'auditeurs et d'optimisation des performances. 1. Le système de routage permet la définition de la structure d'URL et demande la logique de traitement. 2.Lao-éloquente simplifie l'interaction de la base de données. 3. Le système d'authentification et d'autorisation est pratique pour la gestion des utilisateurs. 4. L'événement et l'écoute implémentent la structure de code couplée de manière lâche. 5. L'optimisation des performances améliore l'efficacité de l'application par la mise en cache et la file d'attente.

Quel est le meilleur PHP ou Laravel? Quel est le meilleur PHP ou Laravel? Mar 27, 2025 pm 05:31 PM

PHP et Laravel ne sont pas directement comparables, car Laravel est un cadre basé sur PHP. 1.Php convient aux petits projets ou à un prototypage rapide car il est simple et direct. 2. Laravel convient à de grands projets ou à un développement efficace car il offre des fonctions et des outils riches, mais a une courbe d'apprentissage abrupte et peut ne pas être aussi bon que PHP pur.

Laravel est-il un frontend ou un backend? Laravel est-il un frontend ou un backend? Mar 27, 2025 pm 05:31 PM

LaravelisabackendFrameworkBuiltonPhp, conçue pourwebapplicationdevelopment.itfocusonServer-sidelogic, databasemanagement, andapplicationsstructure, andcanbenegrategratedwithfrontentechnologies likevue.jsorrectForfull-stackdevelopment.

Exemple d'introduction de Laravel Exemple d'introduction de Laravel Apr 18, 2025 pm 12:45 PM

Laravel est un cadre PHP pour la création facile des applications Web. Il fournit une gamme de fonctionnalités puissantes, notamment: Installation: Installez le Laravel CLI globalement avec Composer et créez des applications dans le répertoire du projet. Routage: définissez la relation entre l'URL et le gestionnaire dans Routes / web.php. Voir: Créez une vue dans les ressources / vues pour rendre l'interface de l'application. Intégration de la base de données: fournit une intégration prête à l'emploi avec des bases de données telles que MySQL et utilise la migration pour créer et modifier des tables. Modèle et contrôleur: le modèle représente l'entité de la base de données et le contrôleur traite les demandes HTTP.

Comment apprendre Laravel comment apprendre Laravel gratuitement Comment apprendre Laravel comment apprendre Laravel gratuitement Apr 18, 2025 pm 12:51 PM

Vous voulez apprendre le cadre de Laravel, mais ne souffrez pas de ressources ni de pression économique? Cet article vous fournit un apprentissage gratuit de Laravel, vous apprenant à utiliser des ressources telles que les plateformes en ligne, les documents et les forums communautaires pour jeter une base solide pour votre parcours de développement PHP de la mise en place de maîtrise.

Polyvylity de Laravel: des sites simples aux systèmes complexes Polyvylity de Laravel: des sites simples aux systèmes complexes Apr 13, 2025 am 12:13 AM

Le projet de développement de Laravel a été choisi en raison de sa flexibilité et de sa puissance pour répondre aux besoins de différentes tailles et complexités. Laravel fournit un système de routage, Eloquentorm, une ligne de commande artisanale et d'autres fonctions, soutenant le développement de blogs simples aux systèmes complexes au niveau de l'entreprise.

Fonction de connexion de l'utilisateur de Laravel Fonction de connexion de l'utilisateur de Laravel Apr 18, 2025 pm 12:48 PM

Laravel fournit un cadre Auth complet pour implémenter les fonctions de connexion des utilisateurs, notamment: définir des modèles d'utilisateurs (modèle éloquent), créant des formulaires de connexion (moteur de modèle de lame), rédaction des contrôleurs de connexion (héritage de l'authentification \ loginContrôleur), vérifiant les demandes de connexion (Auth :: tentative) Redirection après la connexion de la connexion, la limitation de la sécurité). De plus, le cadre Auth fournit également des fonctions telles que la réinitialisation des mots de passe, l'enregistrement et la vérification des e-mails. Pour plus de détails, veuillez consulter la documentation de Laravel: https://laravel.com/doc

See all articles