Kernel实例调用handle方法,意味着laravel的核心和公用代码已经准备完毕,此项目正式开始运行
代码:/app/Http/Kernel.php
<?php namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel {
//这是在调用路由之前需要启动的中间件,一般都是核心文件,不要修改
protected $middleware = [
'Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode',
'Illuminate\Cookie\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
];
//这是我们在router.php文件里面或者Controller文件里面,可以使用的Middleware元素,可以自定义加入很多
protected $routeMiddleware = [
'auth' => 'App\Http\Middleware\Authenticate',
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
'test' => 'App\Http\Middleware\testMiddleWare',
];
}
大家看到了,其实这个文件里面没有handle方法,只有一些属性定义,所以真正的handle方法,实在父类里面实现的
代码:…/Illuminate/Foundation/Http/Kernel.php
//好多代码,见几个我看过的扯扯,其他的期待你们补上
//这个很重要,是项目的一些启动引导项,Kernel的重要步骤中,首先就是启动这些文件的bootstrap方法
protected $bootstrappers = [
//检测环境变量文件是否正常
'Illuminate\Foundation\Bootstrap\DetectEnvironment',
//取得配置文件,即把/config/下的所有配置文件读取到容器(app()->make('config')可以查看所有配置信息)
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
//绑定一个名字为log的实例到容器,怎么访问??(app()->make('log'))
'Illuminate\Foundation\Bootstrap\ConfigureLogging',
//设置异常抓取信息,这个还没仔细看,但大概就是这个意思
'Illuminate\Foundation\Bootstrap\HandleExceptions',
//把/config/app.php里面的aliases项利用PHP库函数class_alias创建别名,从此,我们可以使用App::make('app')方式取得实例
'Illuminate\Foundation\Bootstrap\RegisterFacades',
//把/config/app.php里面的providers项,注册到容器
'Illuminate\Foundation\Bootstrap\RegisterProviders',
//运行容器中注册的所有的ServiceProvider中得boot方法
'Illuminate\Foundation\Bootstrap\BootProviders',
];
//真正的handle方法
public function handle($request)
{
try
{
//主要是这行,调度了需要运行的方法
return $this->sendRequestThroughRouter($request);
}
catch (Exception $e)
{
$this->reportException($e);
return $this->renderException($request, $e);
}
}
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
//运行上述$bootstrappers里面包含的文件的bootstrap方法,运行的作用,上面已经注释
$this->bootstrap();
//这是在对URL进行调度之前,也就是运行Route之前,进行的一些准备工作
return (new Pipeline($this->app)) //不解释
->send($request) //继续不解释
//需要运行$this->middleware里包含的中间件
->through($this->middleware)
//运行完上述中间件之后,调度dispatchToRouter方法,进行Route的操作
->then($this->dispatchToRouter());
}
//前奏执行完毕之后,进行Route操作
protected function dispatchToRouter()
{
return function($request)
{
$this->app->instance('request', $request);
//跳转到Router类的dispatch方法
return $this->router->dispatch($request);
};
}
下面就需要根据URL和/app/Http/routes.php文件,进行Route操作
文件:…/Illuminate/Routing/Router.php
//代码好多,挑几个解释
public function dispatch(Request $request)
{
$this->currentRequest = $request;
//在4.2版本里面,Route有一个筛选属性;5.0之后的版本,被Middleware代替
$response = $this->callFilter('before', $request);
if (is_null($response))
{
//继续调度
$response = $this->dispatchToRoute($request);
}
$response = $this->prepareResponse($request, $response);
//在4.2版本里面,Route有一个筛选属性;5.0之后的版本,被Middleware代替
$this->callFilter('after', $request, $response);
return $response;
}
public function dispatchToRoute(Request $request)
{
$route = $this->findRoute($request);
$request->setRouteResolver(function() use ($route)
{
return $route;
});
$this->events->fire('router.matched', [$route, $request]);
$response = $this->callRouteBefore($route, $request);
if (is_null($response))
{
// 只看这一行,还是调度文件
$response = $this->runRouteWithinStack(
$route, $request
);
}
$response = $this->prepareResponse($request, $response);
$this->callRouteAfter($route, $request, $response);
return $response;
}
//干货来了
protected function runRouteWithinStack(Route $route, Request $request)
{
// 取得routes.php里面的Middleware节点
$middleware = $this->gatherRouteMiddlewares($route);
//这个有点眼熟
return (new Pipeline($this->container))
->send($request)
//执行上述的中间件
->through($middleware)
->then(function($request) use ($route)
{
//不容易啊,终于到Controller类了
return $this->prepareResponse(
$request,
//run控制器
$route->run($request)
);
});
}
public function run(Request $request)
{
$this->container = $this->container ?: new Container;
try
{
if ( ! is_string($this->action['uses']))
return $this->runCallable($request);
if ($this->customDispatcherIsBound())
//实际上是运行了这行
return $this->runWithCustomDispatcher($request);
//其实我是直接想运行这行
return $this->runController($request);
}
catch (HttpResponseException $e)
{
return $e->getResponse();
}
}
//继续调度,最终调度到.../Illuminate/Routing/ControllerDispatcher.php文件的dispatch方法
protected function runWithCustomDispatcher(Request $request)
{
list($class, $method) = explode('@', $this->action['uses']);
$dispatcher = $this->container->make('illuminate.route.dispatcher');
return $dispatcher->dispatch($this, $request, $class, $method);
}
文件:…/Illuminate/Routing/ControllerDispatcher.php
public function dispatch(Route $route, Request $request, $controller, $method)
{
$instance = $this->makeController($controller);
$this->assignAfter($instance, $route, $request, $method);
$response = $this->before($instance, $route, $request, $method);
if (is_null($response))
{
//还要调度
$response = $this->callWithinStack(
$instance, $route, $request, $method
);
}
return $response;
}
protected function callWithinStack($instance, $route, $request, $method)
{
//又是Middleware......有没有忘记,官方文档里面Middleware可以加在控制器的构造函数中!!没错,这个Middleware就是在控制器里面申明的
$middleware = $this->getMiddleware($instance, $method);
//又是这个,眼熟吧
return (new Pipeline($this->container))
->send($request)
//再次运行Middleware
->through($middleware)
->then(function($request) use ($instance, $route, $method)
{
运行控制器,返回结果
return $this->call($instance, $route, $method);
});
}
这就是从入口文件到控制器中间,进行的一系列操作