Menu

路由调度之运行路由

简介

运行路由主要做的工作:

  • 1、设置请求对象 Request 的路由分解器属性 routeResolver
  • 2、触发 Illuminate\Routing\Events\RouteMatched 事件,运行此事件关联的监听,即运行监听类中的 handle 方法
  • 3、检测 Laravel 服务容器中有没有绑定 middleware.disable,如果绑定了 middleware.disable,检测绑定的值是不是 true
  • 4、如果绑定了 middleware.disable,且绑定的值是 true,则跳过路由中间件的过滤
  • 5、如果没有绑定 middleware.disable,或者绑定的值是 false,执行路由中间件获取任务

设置路由分解器

protected function runRoute(Request $request, Route $route)
{
    // 调用 Request 对象的 setRouteResolver 方法,设置路由分解器
    $request->setRouteResolver(function () use ($route) {
        return $route;
    });

    $this->events->dispatch(new Events\RouteMatched($route, $request));

    return $this->prepareResponse($request,
        $this->runRouteWithinStack($route, $request)
    );
}
public function setRouteResolver(Closure $callback)
{
    // 将返回路由对象的闭包函数赋值给 routeResolver 属性
    $this->routeResolver = $callback;

    return $this;
}

触发 RouteMatched 事件

protected function runRoute(Request $request, Route $route)
{
    $request->setRouteResolver(function () use ($route) {
        return $route;
    });

    // 触发 `RouteMatched` 事件
    $this->events->dispatch(new Events\RouteMatched($route, $request));

    return $this->prepareResponse($request,
        $this->runRouteWithinStack($route, $request)
    );
}

关于 RouteMatched 事件监听的定义

  • 1、设置 RouteMatched 事件的监听类

    App\Providers\EventServiceProvider

    <?php
    
    namespace App\Providers;
    
    use Illuminate\Support\Facades\Event;
    use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
    
    class EventServiceProvider extends ServiceProvider
    {
      /**
       * The event listener mappings for the application.
       *
       * @var array
       */
      protected $listen = [
          'Illuminate\Routing\Events\RouteMatched' => [
              'App\Listeners\RouteMatchedListener',
          ],
      ];
    
      /**
       * Register any events for your application.
       *
       * @return void
       */
      public function boot()
      {
          parent::boot();
    
          //
      }
    }
    
  • 2、创建监听

    php artisan make:listener RouteMatchedListener
  • 3、编写监听类

    App\Listeners\RouteMatchedListener

    <?php
    
    namespace App\Listeners;
    
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    use Illuminate\Routing\Events\RouteMatched;
    
    class RouteMatchedListener
    {
      /**
       * Create the event listener.
       *
       * @return void
       */
      public function __construct()
      {
          //
      }
    
      /**
       * Handle the event.
       *
       * @param  RouteMatched  $event
       * @return void
       */
      public function handle(RouteMatched $event)
      {
          // 获取请求对象
          $event->request;
          // 获取匹配好的路由对象
          $event->route;
    
          // 如果想在路由中间件过滤前,对请求对象或路由对象进行相关操作,可在此进行相应操作
      }
    }
    

检测 middleware.disable

protected function runRoute(Request $request, Route $route)
{
    $request->setRouteResolver(function () use ($route) {
        return $route;
    });

    $this->events->dispatch(new Events\RouteMatched($route, $request));

    return $this->prepareResponse($request,
        // 调用 runRouteWithinStack 方法,执行路由中间件检测和中间件过滤
        $this->runRouteWithinStack($route, $request)
    );
}
protected function runRouteWithinStack(Route $route, Request $request)
{
    // 检测 Laravel 服务容器中有没有绑定 `middleware.disable`,如果绑定了 `middleware.disable`,检测绑定的值是不是 true
    $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()
                        );
                    });
}

获取路由中间件数组

protected function runRouteWithinStack(Route $route, Request $request)
{    
    $shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
                            $this->container->make('middleware.disable') === true;
    // 执行 gatherRouteMiddleware 方法获取路由中间件数组
    $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()
                        );
                    });
}

讲在最后

  • 关于 gatherRouteMiddleware 方法

    我们自己写的控制器类的实例化,方法名的获取,全部在此方法中执行。具体内容较为复杂,将放在下一章进行讲解。

本篇如有错误、不当或者需补充的内容,请各位同僚多提宝贵意见。

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 0
发起讨论 只看当前版本


暂无话题~