不BB,直接开始。
看一个框架的源码,第一步我们先看入口文件。
laravel的入口文件在public目录下的index.php
require __DIR__.'/../bootstrap/autoload.php';
这玩意是加载composer的一些东西,自动加载有需要的类。具体的也不多说,主要是我还没玩会这玩意。
接着看
$app = require_once __DIR__.'/../bootstrap/app.php';
这里要看bootstrap目录下的app.php文件
这个文件里映入眼帘的就是
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
好吧。new一个application出来。那么我们找到Illuminate\Foundation\Application这个文件
public function __construct($basePath = null)
{
$this->registerBaseBindings();
$this->registerBaseServiceProviders();
$this->registerCoreContainerAliases();
if ($basePath) {
$this->setBasePath($basePath);
}
}
new application时的构造函数长这个样子。写到这的时候,我突然觉得加个序号可能会比较好。
(一) new Application的过程
1.1先是注册基本绑定,也就是 $this->registerBaseBindings();这个方法里的内容
protected function registerBaseBindings()
{
static::setInstance($this);
$this->instance('app', $this);
$this->instance('Illuminate\Container\Container', $this);
}
巨简单的过程,就是把实例化的的application 赋值给app和Illuminate\Container\Container
1.2注册基本的服务提供者。$this->registerBaseServiceProviders();
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this));
$this->register(new RoutingServiceProvider($this));
}
这里通过名字可以感觉出是注册了事件服务提供者和路由服务提供者
1.3注册核心类名的别名$this->registerCoreContainerAliases();
public function registerCoreContainerAliases()
{
$aliases = [
'app' => ['Illuminate\Foundation\Application', 'Illuminate\Contracts\Container\Container', 'Illuminate\Contracts\Foundation\Application'],
'auth' => ['Illuminate\Auth\AuthManager', 'Illuminate\Contracts\Auth\Factory'],
'auth.driver' => ['Illuminate\Contracts\Auth\Guard'],
'blade.compiler' => ['Illuminate\View\Compilers\BladeCompiler'],
'cache' => ['Illuminate\Cache\CacheManager', 'Illuminate\Contracts\Cache\Factory'],
'cache.store' => ['Illuminate\Cache\Repository', 'Illuminate\Contracts\Cache\Repository'],
'config' => ['Illuminate\Config\Repository', 'Illuminate\Contracts\Config\Repository'],
'cookie' => ['Illuminate\Cookie\CookieJar', 'Illuminate\Contracts\Cookie\Factory', 'Illuminate\Contracts\Cookie\QueueingFactory'],
'encrypter' => ['Illuminate\Encryption\Encrypter', 'Illuminate\Contracts\Encryption\Encrypter'],
'db' => ['Illuminate\Database\DatabaseManager'],
'db.connection' => ['Illuminate\Database\Connection', 'Illuminate\Database\ConnectionInterface'],
'events' => ['Illuminate\Events\Dispatcher', 'Illuminate\Contracts\Events\Dispatcher'],
'files' => ['Illuminate\Filesystem\Filesystem'],
'filesystem' => ['Illuminate\Filesystem\FilesystemManager', 'Illuminate\Contracts\Filesystem\Factory'],
'filesystem.disk' => ['Illuminate\Contracts\Filesystem\Filesystem'],
'filesystem.cloud' => ['Illuminate\Contracts\Filesystem\Cloud'],
'hash' => ['Illuminate\Contracts\Hashing\Hasher'],
'translator' => ['Illuminate\Translation\Translator', 'Symfony\Component\Translation\TranslatorInterface'],
'log' => ['Illuminate\Log\Writer', 'Illuminate\Contracts\Logging\Log', 'Psr\Log\LoggerInterface'],
'mailer' => ['Illuminate\Mail\Mailer', 'Illuminate\Contracts\Mail\Mailer', 'Illuminate\Contracts\Mail\MailQueue'],
'auth.password' => ['Illuminate\Auth\Passwords\PasswordBrokerManager', 'Illuminate\Contracts\Auth\PasswordBrokerFactory'],
'auth.password.broker' => ['Illuminate\Auth\Passwords\PasswordBroker', 'Illuminate\Contracts\Auth\PasswordBroker'],
'queue' => ['Illuminate\Queue\QueueManager', 'Illuminate\Contracts\Queue\Factory', 'Illuminate\Contracts\Queue\Monitor'],
'queue.connection' => ['Illuminate\Contracts\Queue\Queue'],
'queue.failer' => ['Illuminate\Queue\Failed\FailedJobProviderInterface'],
'redirect' => ['Illuminate\Routing\Redirector'],
'redis' => ['Illuminate\Redis\Database', 'Illuminate\Contracts\Redis\Database'],
'request' => ['Illuminate\Http\Request', 'Symfony\Component\HttpFoundation\Request'],
'router' => ['Illuminate\Routing\Router', 'Illuminate\Contracts\Routing\Registrar'],
'session' => ['Illuminate\Session\SessionManager'],
'session.store' => ['Illuminate\Session\Store', 'Symfony\Component\HttpFoundation\Session\SessionInterface'],
'url' => ['Illuminate\Routing\UrlGenerator', 'Illuminate\Contracts\Routing\UrlGenerator'],
'validator' => ['Illuminate\Validation\Factory', 'Illuminate\Contracts\Validation\Factory'],
'view' => ['Illuminate\View\Factory', 'Illuminate\Contracts\View\Factory'],
];
foreach ($aliases as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}
这个方法更简单,就是一个别名数组,然后通过for循环调用$this->alias()给Application类的父类Container里的aliases数组里。
1.4设置基本路径,我们在new Application时传入的 realpath(DIR.’/../’)这个参数赋值给基本路径
(二)注册共享的Kernel和异常处理器
我们的app也new好了,我们接着app.php里往下走可以看到
$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
);
这三个具体干嘛的我们以后分析,然后app.php最后返回的是app实例
(三)处理请求和响应
app.php文件执行完以后回到index.php 可以看到
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$kernel->terminate($request, $response);
3.1解析Illuminate\Contracts\Http\Kernel,实例化App\Http\Kernel
3.2实例化后的kernel处理本次请求。这里$kernel->handle()传入的参数是一个request。
这里的request是经过Symfony封装的请求对象。讲道理看到这的时候我有点懵逼。卧槽,我刚开始学laravel,还没整明白呢,就又多了一个Symfony要学,至少得了解怎么封装的请求对象。好烦呀。。。
3.3是将请求处理后的返回结果发送到浏览器里
3.4处理继承自TerminableMiddleware接口的中间件(Session)并结束应用生命周期。
以上就是laravel框架里执行一次请求所要经历的生命周期。
具体的如何注册如何加载如何封装请求,我会随着自己知识的积累和分析源码来做出解答。
顺便,我也是刚开始学习laravel。一起加油!