<?php /*设置脚本开始时间 define('LARAVEL_START', microtime(true)); 引入composer的自动加载,在composer.json中可以看出相当于 require('app/*') require('database/*') require('vendor/*') 之后使用时只要引入命名空间即可 */ require __DIR__.'/../bootstrap/autoload.php'; $app = require_once __DIR__.'/../bootstrap/app.php'; /*在phpstrom中ctrl+左键单击查看app.php代码。*/
/*app.php代码如下:*/ /*首先创建app服务容器,即ioc容器,稍后分析*/ $app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') ); /* 看官方文档可知, singleton 方法绑定一个只需要解析一次的类或接口到容器,然后接下来对容器的调用将会返回同一个实例 即以后需要使用Illuminate\Contracts\Http\Kernel这个类时,会返回App\Http\Kernel 使用代码 $app->make('Illuminate\Contracts\Http\Kernel') */ /* 在laravel中Contracts(契约)文件夹里面的都是interfere类 实现时都在Foundation这个文件夹中 而查看App\Http\Kernel会发现它继承了实现接口类的类 */ /* 这里绑定的是http启动的一些启动服务(session。env。config等)和中间件。以后分析。 */ $app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class ); /* 这里绑定的是控制台用的服务,即php artisan 如果上线了可以省去。 */ $app->singleton( Illuminate\Contracts\Console\Kernel::class, App\Console\Kernel::class ); /* 绑定错误提示类 上线后可以省去。 */ $app->singleton( Illuminate\Contracts\Debug\ExceptionHandler::class, App\Exceptions\Handler::class ); return $app;
/*继续查看index.php*/ /* 这里解析http的核心 */ $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class); /* 处理请求,生成响应 这里的handle函数是一大难点。其实现贼复杂 */ $response = $kernel->handle( /* 这里利用symfont的http request解析http请求 里面有post。get。文件。路径等很多信息。 */ $request = Illuminate\Http\Request::capture() ); /*发送响应*/ $response->send(); /*后续处理,比如写log等*/ $kernel->terminate($request, $response);
/*由app.php里面的singleton很容易得知handle函数的所在*/ public function handle($request) { try { /*这是symfont的允许在路由中使用GET和POST以外的HTTP方法 */ $request->enableHttpMethodParameterOverride(); /*把request交给router处理,首先肯定是要匹配的你在route里面定义的方法*/ $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); } /*分发事件,让事件监听获取信息,以后说*/ event(new Events\RequestHandled($request, $response)); return $response; }
/*然后我们专注于sendRequestThroughRouter这函数*/ protected function sendRequestThroughRouter($request) { /* 绑定一个实例。 laravel实现3种绑定,bind singleton instance。每次绑定如果名字相同会覆盖掉上次绑定的。 bind每次make返回的都是新的实例 singleton每次make返回的都是同一个实例 instance每次返回的都是绑定时给的实例 */ $this->app->instance('request', $request); /*未知作用*/ Facade::clearResolvedInstance('request'); /*启动初始服务,比如config。env等,以后有机会分析*/ $this->bootstrap(); /*利用管道类处理请求,先绑定app容器,然后发送request请求,通过中间件,最后匹配路由,并执行route里面定义的方法,生成并返回reponse,其中源码绕来绕去就不一一解析*/ return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }