


Interprétation de base du middleware Laravel (Middleware)
Cet article partage principalement avec vous l'interprétation principale du middleware Laravel (Middleware) dans Laravel qui joue le rôle de filtrer l'objet de requête HTTP (Request) entrant dans l'application et améliorer la sortie.Le rôle de l'objet de réponse HTTP de l'application (Reponse) et l'application de plusieurs middlewares peuvent filtrer les requêtes couche par couche et améliorer progressivement la réponse. Cela réalise le découplage du programme. S'il n'y a pas de middleware, nous devons effectuer ces étapes dans le contrôleur, ce qui entraînera sans aucun doute une surcharge du contrôleur.
Pour donner un exemple simple, sur une plateforme de e-commerce, un utilisateur peut être soit un utilisateur ordinaire effectuant des achats sur la plateforme, soit un utilisateur vendeur après avoir ouvert une boutique. Le système d'utilisateurs de ces deux types d'utilisateurs est. souvent le même. Il suffit alors d'appliquer deux middlewares dans le contrôleur auxquels seuls les utilisateurs vendeurs peuvent accéder pour compléter l'authentification de l'identité des utilisateurs vendeurs :
class MerchantController extends Controller{ public function __construct() { $this->middleware('auth'); $this->middleware('mechatnt_auth'); } }
L'authentification générale de l'utilisateur est effectuée dans le middleware d'authentification. Après succès, la requête HTTP sera envoyée au middleware Merchant_auth pour authentifier les informations de l'utilisateur du commerçant. La requête HTTP peut saisir la méthode du contrôleur à laquelle elle souhaite accéder. À l'aide d'un middleware, nous pouvons extraire ces codes d'authentification dans le middleware correspondant, et nous pouvons librement combiner plusieurs middlewares en fonction des besoins pour filtrer les requêtes HTTP.
Un autre exemple est le middleware VerifyCsrfToken
que Laravel applique automatiquement à toutes les routes. Lorsque la requête HTTP entre dans l'application et passe par le middleware VerifyCsrfToken
, le jeton sera vérifié pour empêcher la falsification de requêtes intersites. . La réponse HTTP sera vérifiée avant de quitter l'application. Ajoutez les cookies appropriés à la réponse. (À partir de Laravel 5.5, le middleware CSRF n'est automatiquement appliqué qu'au routage Web)
Dans l'exemple ci-dessus, celui qui filtre la requête s'appelle le pré-middleware, et celui qui complète la réponse s'appelle le post-middleware. Une image peut être utilisée pour marquer l'ensemble du processus :
Ce qui précède décrit le rôle du middleware dans Laravel et quel type de code doit être déplacé du contrôleur vers le middleware. comment Pour définir et utiliser votre propre middleware laravel, veuillez vous référer à la documentation officielle.
Jetons un coup d'œil à la manière dont le middleware est implémenté dans Laravel. La conception du middleware applique un modèle de conception appelé décorateur.
Une fois que Laravel a instancié l'application, il analysera l'objet Http Kernel du conteneur de service. Il ressort également du nom de la classe que Http Kernel est le noyau responsable des requêtes et des réponses HTTP dans Laravel.
, car la classe d'implémentation de l'interface est liée à
, donc $kernel est en fait un objet de/** * @var \App\Http\Kernel $kernel */$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); $response = $kernel->handle( $request = Illuminate\Http\Request::capture() ); $response->send(); $kernel->terminate($request, $response);classe.
Après avoir analysé le noyau Http, Laravel transmet l'objet de requête entrant dans l'application à la méthode handle du noyau Http. La méthode handle est responsable du traitement de l'objet de requête entrant dans l'application et du renvoi de l'objet de réponse. index.php
bootstrap/app.php
IlluminateContractsHttpKernel
AppHttpKernel
AppHttpKernel
L'article contient une explication détaillée de cette partie. Laravel transmet l'objet de requête via l'objet Pipeline. Dans le Pipeline, l'objet de requête atteint une action du contrôleur via la pré-opération du middleware défini dans le noyau HTTP ou le traitement de fermeture directe pour obtenir l'objet de réponse. Regardez ces méthodes dans Pipeline : La fonction ci-dessus semble un peu déroutante. Examinons d'abord l'explication de ses paramètres de fonction de rappel dans array_reduce :
/** * Handle an incoming HTTP request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */public function handle($request){ try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app['events']->dispatch( new Events\RequestHandled($request, $response) ); return $response; }
$this->sendRequestThroughRouter($request)
/** * Send the given request through the middleware / router. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */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()); }Ensuite, nous examinons le rappel de array_reduce :
//Pipeline protected function getSlice(){ return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { try { $slice = parent::getSlice(); return call_user_func($slice($stack, $pipe), $passable); } catch (Exception $e) { return $this->handleException($passable, $e); } catch (Throwable $e) { return $this->handleException($passable, new FatalThrowableError($e)); } }; }; }//Pipleline的父类BasePipeline的getSlice方法protected function getSlice(){ return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { if ($pipe instanceof Closure) { return call_user_func($pipe, $passable, $stack); } elseif (! is_object($pipe)) { //解析中间件名称和参数 ('throttle:60,1') list($name, $parameters) = $this->parsePipeString($pipe); $pipe = $this->container->make($name); $parameters = array_merge([$passable, $stack], $parameters); } else{ $parameters = [$passable, $stack]; } //$this->method = handle return call_user_func_array([$pipe, $this->method], $parameters); }; }; }
注:在Laravel5.5版本里 getSlice这个方法的名称换成了carray, 两者在逻辑上没有区别,所以依然可以参照着5.5版本里中间件的代码来看本文。
getSlice会返回一个闭包函数, $stack在第一次调用getSlice时它的值是$firstSlice, 之后的调用中就它的值就是这里返回的值个闭包了:
$stack = function ($passable) use ($stack, $pipe) { try { $slice = parent::getSlice(); return call_user_func($slice($stack, $pipe), $passable); } catch (Exception $e) { return $this->handleException($passable, $e); } catch (Throwable $e) { return $this->handleException($passable, new FatalThrowableError($e)); } };
getSlice返回的闭包里又会去调用父类的getSlice方法,他返回的也是一个闭包,在闭包会里解析出中间件对象、中间件参数(无则为空数组), 然后把$passable(请求对象), $stack和中间件参数作为中间件handle方法的参数进行调用。
上面封装的有点复杂,我们简化一下,其实getSlice的返回值就是:
$stack = function ($passable) use ($stack, $pipe) { //解析中间件和中间件参数,中间件参数用$parameter代表,无参数时为空数组 $parameters = array_merge([$passable, $stack], $parameters) return $pipe->handle($parameters) };
array_reduce每次调用callback返回的闭包都会作为参数$stack传递给下一次对callback的调用,array_reduce执行完成后就会返回一个嵌套了多层闭包的闭包,每层闭包用到的外部变量$stack都是上一次之前执行reduce返回的闭包,相当于把中间件通过闭包层层包裹包成了一个洋葱。
在then方法里,等到array_reduce执行完返回最终结果后就会对这个洋葱闭包进行调用:
return call_user_func( array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable);
这样就能依次执行中间件handle方法,在handle方法里又会去再次调用之前说的reduce包装的洋葱闭包剩余的部分,这样一层层的把洋葱剥开直到最后。通过这种方式让请求对象依次流过了要通过的中间件,达到目的地Http Kernel 的dispatchToRouter
方法。
通过剥洋葱的过程我们就能知道为什么在array_reduce之前要先对middleware数组进行反转, 因为包装是一个反向的过程, 数组$pipes中的第一个中间件会作为第一次reduce执行的结果被包装在洋葱闭包的最内层,所以只有反转后才能保证初始定义的中间件数组中第一个中间件的handle方法会被最先调用。
上面说了Pipeline传送请求对象的目的地是Http Kernel 的dispatchToRouter
方法,其实到远没有到达最终的目的地,现在请求对象了只是刚通过了\App\Http\Kernel
类里$middleware
属性里罗列出的几个中间件:
protected $middleware = [ \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \App\Http\Middleware\TrustProxies::class, ];
当请求对象进入dispatchToRouter
方法后,请求对象在被Router dispatch派发给路由时会进行收集路由上应用的中间件和控制器里应用的中间件。
public function dispatch(Request $request){ $this->currentRequest = $request; $response = $this->dispatchToRoute($request); return $this->prepareResponse($request, $response); }public function dispatchToRoute(Request $request){ return $this->runRoute($request, $this->findRoute($request)); }protected function runRouteWithinStack(Route $route, Request $request){ $shouldSkipMiddleware = $this->container->bound('middleware.disable') && $this->container->make('middleware.disable') === true; //收集路由和控制器里应用的中间件 $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route); return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(function ($request) use ($route) { return $this->prepareResponse( $request, $route->run() ); }); }
收集完路由和控制器里应用的中间件后,依赖时利用Pipeline对象来传送请求对象通过收集上来的这些中间件然后到达最终的目的地,在这里会执行路由对应的控制器方法生成响应对象,然后响应对象会依次来通过上面应用的所有中间件的后置操作,最终离开应用被发送给客户端。
限于篇幅和为了文章的可读性,收集路由和控制器中间件然后执行路由对应的处理方法的过程我就不在这里详述了,感兴趣的同学可以自己去看Router的源码,本文的目的还是主要为了梳理laravel是如何设计中间件的以及如何执行它们的,希望能对感兴趣的朋友有帮助。
相关推荐:
laravel中间件中的Closure $next是什么意思
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!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

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

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

Clothoff.io
Dissolvant de vêtements AI

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 !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

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

Sujets chauds

Lorsque vous choisissez un cadre PHP approprié, vous devez considérer de manière approfondie en fonction des besoins du projet: Laravel convient au développement rapide et fournit des moteurs de modèle éloquente et de lame, qui sont pratiques pour le fonctionnement de la base de données et le rendu de formulaire dynamique; Symfony est plus flexible et adapté aux systèmes complexes; Codeigniter est léger et adapté à des applications simples avec des exigences de performance élevées. 2. Pour assurer la précision des modèles d'IA, nous devons commencer avec une formation de données de haute qualité, une sélection raisonnable des indicateurs d'évaluation (tels que la précision, le rappel, la valeur F1), l'évaluation régulière des performances et le réglage du modèle, et assurer la qualité du code grâce aux tests unitaires et aux tests d'intégration, tout en surveillant continuellement les données d'entrée pour empêcher la dérive des données. 3. De nombreuses mesures sont nécessaires pour protéger la confidentialité des utilisateurs: crypter et stocker des données sensibles (comme AES

Il existe trois façons principales de définir des variables d'environnement dans PHP: 1. Configuration globale via Php.ini; 2. Passé via un serveur Web (tel que setenv d'Apache ou Fastcgi_param de Nginx); 3. Utilisez la fonction PUTENV () dans les scripts PHP. Parmi eux, PHP.ini convient aux configurations globales et modifiées, la configuration du serveur Web convient aux scénarios qui doivent être isolés et PUTENV () convient aux variables temporaires. Les stratégies de persistance incluent des fichiers de configuration (tels que PHP.ini ou la configuration du serveur Web), les fichiers .env sont chargés de bibliothèque Dotenv et l'injection dynamique de variables dans les processus CI / CD. Les informations sensibles à la gestion de la sécurité doivent être évitées à code dur et il est recommandé de l'utiliser.

Pour permettre aux conteneurs PHP de prendre en charge la construction automatique, le noyau réside dans la configuration du processus d'intégration continue (CI). 1. Utilisez Dockerfile pour définir l'environnement PHP, y compris l'image de base, l'installation d'extension, la gestion de la dépendance et les paramètres d'autorisation; 2. Configurez des outils CI / CD tels que GitLabci et définissez les étapes de construction, de test et de déploiement via le fichier .gitlab-ci.yml pour réaliser une construction, un test et un déploiement automatique; 3. Intégrer des cadres de test tels que PHPUnit pour s'assurer que les tests sont automatiquement exécutés après les modifications du code; 4. Utiliser des stratégies de déploiement automatisées telles que Kubernetes pour définir la configuration de déploiement via le fichier de déploiement.yaml; 5. Optimiser Dockerfile et adopter une construction en plusieurs étapes

Pour créer une plate-forme de paiement de contenu PHP, il est nécessaire de créer un système de gestion des utilisateurs, de gestion du contenu, de paiement et d'autorisation. Tout d'abord, établissez un système d'authentification utilisateur et utilisez JWT pour obtenir une authentification légère; Deuxièmement, concevez l'interface de gestion backend et les champs de base de données pour gérer le contenu payant; Troisièmement, intégrez le paiement Alipay ou WeChat et assurez-vous la sécurité du processus; Quatrièmement, contrôlez les droits d'accès aux utilisateurs via la session ou les cookies. Le choix du cadre Laravel peut améliorer l'efficacité du développement, utiliser des filigranes et la gestion des utilisateurs pour empêcher le vol de contenu, l'optimisation des performances nécessite une amélioration coordonnée de la configuration du code, de la base de données, du cache et du serveur, et des politiques claires doivent être formulées et des comportements malveillants doivent être évités.

L'idée principale de PHP combinant l'IA pour l'analyse du contenu vidéo est de permettre à PHP de servir de "colle" backend, de télécharger d'abord la vidéo sur le stockage du cloud, puis d'appeler les services d'IA (tels que Google CloudVideoai, etc.) pour une analyse asynchrone; 2. PHP analyse les résultats JSON, extraire les personnes, les objets, les scènes, la voix et autres informations pour générer des balises intelligentes et les stocker dans la base de données; 3. L'avantage est d'utiliser l'écosystème Web mature de PHP pour intégrer rapidement les capacités d'IA, qui convient aux projets avec les systèmes PHP existants pour mettre en œuvre efficacement; 4. Les défis courants incluent un traitement de fichiers important (directement transmis au stockage cloud avec des URL pré-signées), des tâches asynchrones (introduction des files d'attente de messages), un contrôle des coûts (analyse à la demande, une surveillance du budget) et une optimisation des résultats (standardisation de l'étiquette); 5. Les étiquettes intelligentes améliorent considérablement le visuel

La gestion de la permission des utilisateurs est le mécanisme central pour réaliser la monétisation des produits dans le développement de PHP. Il sépare les utilisateurs, les rôles et les autorisations via un modèle de contrôle d'accès basé sur les rôles (RBAC) pour obtenir une allocation et une gestion d'autorisation flexibles. Les étapes spécifiques incluent: 1. Concevoir trois tables d'utilisateurs, rôles et autorisations et deux tables intermédiaires de user_roles et de role_permissions; 2. Implémentez les méthodes de vérification de l'autorisation dans le code telles que $ user-> can ('edit_post'); 3. Utilisez du cache pour améliorer les performances; 4. Utiliser le contrôle de l'autorisation pour réaliser la superposition des fonctions du produit et les services différenciés, soutenant ainsi le système d'adhésion et les stratégies de tarification; 5. Évitez la permission que la granularité est trop grossière ou trop fine, et utilisez "l'investissement"

Les éloquents de Laravel sont un outil qui résume la logique de requête commune, divisée en portée locale et en portée mondiale. 1. La portée locale est définie avec une méthode commençant par la portée et doit être appelée explicitement, comme POST :: publiée (); 2. La portée globale est automatiquement appliquée à toutes les requêtes, souvent utilisées pour la suppression douce ou les systèmes multi-locataires, et l'interface de portée doit être implémentée et enregistrée dans le modèle; 3. La portée peut être équipée de paramètres, tels que le filtrage des articles par année ou par mois, et les paramètres correspondants sont passés lors de l'appel; 4. Faites attention aux spécifications de dénomination, aux appels de chaîne, à la désactivation temporaire et à l'expansion de la combinaison lors de l'utilisation pour améliorer la clarté du code et la réutilisabilité.

Le cache de configuration de Laravel améliore les performances en fusionnant tous les fichiers de configuration dans un seul fichier de cache. L'activation du cache de configuration dans un environnement de production peut réduire les opérations d'E / S et l'analyse de fichiers sur chaque demande, accélérant ainsi le chargement de configuration; 1. Il doit être activé lorsque l'application est déployée, la configuration est stable et aucune modification fréquente n'est requise; 2. Après l'activation, modifiez la configuration, vous devez ré-paraître phpartisanconfig: cache pour prendre effet; 3. Évitez d'utiliser une logique dynamique ou des fermetures qui dépendent des conditions d'exécution dans le fichier de configuration; 4. Lors du dépannage des problèmes, vous devez d'abord effacer le cache, vérifiez les variables .env et re-cache.
