Laravel源码分析 - 生存周期

如果仅仅想使用 laravel 开发项目,你只需要看官方的文档就可以做到。开发过程中遇到的大部分问题都可以使用搜索引擎找到答案,剩下刁钻的大部分问题又可以向技术论坛提问来获取答案。但即使这样,仍旧会有无法解决的问题,这时候你就会在这里卡壳,项目无法进行下去,于是你加班…

但如果你已经学习过源码,对它很熟悉,那么你就能找到问题的源头,来修复它。

学习好的项目源码,可以提升你的编程能力,规范你的项目结构、代码格式、命名方式等。

所以我把学习 laravel 源码的过程记录下来,这会是一个系列。

根据 public/index.php 来分析比较浅显的声明周期

index.phpGithub
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// composer 加载器
require __DIR__.'/../vendor/autoload.php';

// 初始化 Application(它也是一个容器)
$app = require_once __DIR__.'/../bootstrap/app.php';

// 解析 HTTP 核心处理器
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

// 使用处理器处理请求并返回响应对象
// 你的逻辑代码基本都会在这里执行,最重要的部分
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);

// 生成响应
$response->send();

// 最后结束运行,这里会处理在中间件中定义的 terminate 方法
$kernel->terminate($request, $response);

下面分析几个组成部分

初始化 App

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function __construct($basePath = null)
{
// 根据传入的根路径,设置应用服务文件的各个路径
if ($basePath) {
$this->setBasePath($basePath);
}

// 注册基本绑定服务
$this->registerBaseBindings();

// 注册基础服务提供者
$this->registerBaseServiceProviders();

// 设置服务别名
$this->registerCoreContainerAliases();
}

注册基本绑定服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected function registerBaseBindings()
{
// 绑定自身静态单例
static::setInstance($this);

// 把自身以单例形式绑定到 app 名称上
$this->instance('app', $this);

// 把自身以单例形式绑定到 Container::class 类名上
$this->instance(Container::class, $this);

// 把包自动发现服务绑定到 PackageManifest::class 类名上
$this->instance(PackageManifest::class, new PackageManifest(
new Filesystem, $this->basePath(), $this->getCachedPackagesPath()
));
}

注册基础服务提供者

1
2
3
4
5
6
7
8
9
protected function registerBaseServiceProviders()
{
// 注册事件服务提供者
$this->register(new EventServiceProvider($this));
// 注册日志服务提供者
$this->register(new LogServiceProvider($this));
// 注册路由服务提供者
$this->register(new RoutingServiceProvider($this));
}

设置服务别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public function registerCoreContainerAliases()
{
foreach ([
'app' => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class],
'auth' => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
'auth.driver' => [\Illuminate\Contracts\Auth\Guard::class],
'blade.compiler' => [\Illuminate\View\Compilers\BladeCompiler::class],
'cache' => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
'cache.store' => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class],
'config' => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class],
'cookie' => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class],
'encrypter' => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class],
'db' => [\Illuminate\Database\DatabaseManager::class],
'db.connection' => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
'events' => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
'files' => [\Illuminate\Filesystem\Filesystem::class],
'filesystem' => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class],
'filesystem.disk' => [\Illuminate\Contracts\Filesystem\Filesystem::class],
'filesystem.cloud' => [\Illuminate\Contracts\Filesystem\Cloud::class],
'hash' => [\Illuminate\Hashing\HashManager::class],
'hash.driver' => [\Illuminate\Contracts\Hashing\Hasher::class],
'translator' => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
'log' => [\Illuminate\Log\LogManager::class, \Psr\Log\LoggerInterface::class],
'mailer' => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
'auth.password' => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class],
'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class],
'queue' => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class],
'queue.connection' => [\Illuminate\Contracts\Queue\Queue::class],
'queue.failer' => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class],
'redirect' => [\Illuminate\Routing\Redirector::class],
'redis' => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class],
'request' => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class],
'router' => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],
'session' => [\Illuminate\Session\SessionManager::class],
'session.store' => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class],
'url' => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class],
'validator' => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class],
'view' => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class],
] as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}


public function alias($abstract, $alias)
{
// 以别名为键,抽象的名为值
$this->aliases[$alias] = $abstract;

// 以抽象的名为键的数组别名
$this->abstractAliases[$abstract][] = $alias;
}

处理请求,生成响应

bootstrap/app.php 初始化 App 后,还绑定了3个单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// http 内核
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
// console 控制台内核
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
// 异常处理
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);

这之后在 index.php 继续往下执行

1
2
3
4
5
6
7
8
9
10
11
// 上一步已绑定了 http 内核单例,这时就可以解析出它
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

// 使用它处理请求,返回响应
$response = $kernel->handle(
// 创建 Request 实例
$request = Illuminate\Http\Request::capture()
);

// 生成响应
$response->send();

结束运行

最后内核会调用 terminate 方法来终止此次请求

1
2
3
4
5
6
7
8
public function terminate($request, $response)
{
// 遍历中间件并执行每个它们的 terminate 方法(如果存在此方法)
$this->terminateMiddleware($request, $response);

// 执行终止回调
$this->app->terminate();
}
0%