laravel是单一入口模式,所有请求从public/index.php进入
define('LARAVEL_START', microtime(true));
require __DIR__.'/../vendor/autoload.php';
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);
我们都知道 web程序做的事情就是:
1.用户从浏览器发送请求,请求
2.程序接收请求进行计算,网页程序
3.运算结果返回给浏览器,网页响应
index文件中的$request $kernel $resopnse 就是对应着请求、计算、响应
请求部分使用syfmony的request组件对刘篮球发出的请求头信息进行打包收集,形成一个对象来方便我们操作
$kernel算是laravel的请求处理核心了,通过request里的url找到相应路由的控制器,
执行后返回视图等响应,并将$response输出至浏览器。
步骤解析
第一步:define('LARAVEL_START', microtime(true));
首先计算启动框架的时间,但是在整个生命周期里面却没有用到过
第二步:require __DIR__.'/../vendor/autoload.php';
这行代码引入了composer启动文件,PHP所需要的文件,都需要在这里加载,laravel有一个composer.json文件,写入了我们需要的依赖,composer启动的时候,会把这些依赖缓存成key/value数组,出发spl_autoload函数进行加载
第三步:$app = require_once __DIR__.'/../bootstrap/app.php';
这行数据实例化了一个$app的应用程序对象,这是个关键,让我们看一下这个文件
<?php
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
return $app;
它做的事情不多 显示实例化了一个application对象,然后把http和控制台kernel还有异常处理实例绑定到了这个对象中,返回给了index文件
我们来解析一下实例化application对象的过程
public function __construct($basePath = null)
{
if ($basePath) {
$this->setBasePath($basePath);
}
$this->registerBaseBindings();
$this->registerBaseServiceProviders();
$this->registerCoreContainerAliases();
}
构造函数做了下面的四件事:
第一件:
加载了项目的一些路径存储到了$app对象里面,我们查看setBasePath方法
public function setBasePath($basePath)
{
$this->basePath = rtrim($basePath, '\/');
$this->bindPathsInContainer();
return $this;
}
在查看bindPathsInContainer方法
protected function bindPathsInContainer()
{
$this->instance('path', $this->path());
$this->instance('path.base', $this->basePath());
$this->instance('path.lang', $this->langPath());
$this->instance('path.config', $this->configPath());
$this->instance('path.public', $this->publicPath());
$this->instance('path.storage', $this->storagePath());
$this->instance('path.database', $this->databasePath());
$this->instance('path.resources', $this->resourcePath());
$this->instance('path.bootstrap', $this->bootstrapPath());
}
具体的实现代码在其父类Container类的instance方法中,代码很简单就一句是$this->instances[$abstract] = $instance;。
public function instance($abstract, $instance)
{
$this->removeAbstractAlias($abstract);
$isBound = $this->bound($abstract);
unset($this->aliases[$abstract]);
// We'll check to determine if this type has been bound before, and if it has
// we will fire the rebound callbacks registered with the container and it
// can be updated with consuming classes that have gotten resolved here.
$this->instances[$abstract] = $instance;
if ($isBound) {
$this->rebound($abstract);
}
return