laravel大致的运行过程,先记录一下。 当然我是在看到了 这个博文https://my.oschina.net/falcon10086/blog/647507,写的很棒。
laravel唯一的路口文件 /public/index.php
一步一步来看
require __DIR__.'/../bootstrap/autoload.php';
引入类加载器,查看autoload.php文件
define('LARAVEL_START', microtime(true));
require __DIR__.'/../vendor/autoload.php';
$compiledPath = __DIR__.'/cache/compiled.php';
if (file_exists($compiledPath)) {
require $compiledPath;
}
第一行代码定义程序运行的开始事件;
第二段代码请求了vendor/autoload.php文件,也就是说使用了composer自带的类加载器。
第三段和第四段代码用来优化效率。
现在继续看index.php文件
$app = require_once __DIR__.'/../bootstrap/app.php';
查看bootstrap/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;
先创建了一个 Illuminate\Foundation\Application 实例,该类继承Illuminate\Container\Container,调用其singleton()方法绑定接口和类,最后返回实例,这里是一个单例。
看一下 Illuminate\Foundation\Application 构造函数
public function __construct($basePath = null)
{
$this->registerBaseBindings();
$this->registerBaseServiceProviders();
$this->registerCoreContainerAliases();
if ($basePath) {
$this->setBasePath($basePath);
}
}
$this->registerBaseBindings()方法
protected function registerBaseBindings()
{
/*
* 首先需要明白当前类继承自 Illuminate\Container\Container
*
* setInstance 是 Illuminate\Container\Container 中的方法将类和当前对象绑定, 当然这样说是为了跟容易表示,下面的注释也是如此
*/
static::setInstance($this);
/*
* 将'app'和当前对象放在 Illuminate\Container\Container 的 instances 数组中,
* 形成一个映射,当然当前类继承自 Illuminate\Container\Container 也就是调用自己的 instance() 方法
* 这样'app'指向了当前对象,实现绑定。
*/
$this->instance('app', $this);
/*
* 和上面的类似,绑定
*/
$this->instance('Illuminate\Container\Container', $this);
}
$this->registerBaseServiceProviders()
protected function registerBaseServiceProviders()
{
/*
* 依赖注入: 当前对象被注入到 EventServiceProvider、RoutingServiceProvider 中
*/
$this->register(new EventServiceProvider($this));
$this->register(new RoutingServiceProvider($this));
}
注册服务提供器。
$this->registerCoreContainerAliases()
public function registerCoreContainerAliases()
{
$aliases = [
'app' => ['Illuminate\Foundation\Application', 'Illuminate\Contracts\Container\Container', 'Illuminate\Contracts\Foundation\Application']
...
];
foreach ($aliases as $key => $aliases) {
foreach ((array) $aliases as $alias) {
$this->alias($key, $alias);
}
}
}
注册核心类的别名,简化命名; aliases 数组中一个复杂的名字对应别名。
例如下面的:
Illuminate\Foundation\Application => app;
Illuminate\Contracts\Container\Container => app;
foreach 就是具体的绑定。
现在分析app.php中的$app->singleton()。该方法将接口和具体实现类绑定在一起,之后用到接口的时候会调用对应的具体实现。该部分源码比较复杂,可以自己看一下,主要部分是 Illuminate\Container\Container 的 make 和 build 方法。
现在再次回到index.php
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
由于 bootstrap/app.php 中绑定了接口和具体实现,这里调用 make 就会创建App\Http\Kernel::class 类实例。
最后kernel 处理 http 请求,接收请求, 发送响应, 终止程序,处理一些收尾的工作。