入口文件index.php
<?php
define('LARAVEL_START', microtime(true));
//注册自动加载,引入了Composer提供的依赖注入,无需手动加载任何类(加载项目依赖)
require __DIR__.'/../vendor/autoload.php';
//初始化应用,可以理解为加载框架,准备好应用的环境以及配置,为启动应用准备
$app = require_once __DIR__.'/../bootstrap/app.php';
//运行应用,从容器中解析kernel对象,初始化,实际解析对象App\Http\Kernel
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
//捕获请求,处理请求并返回响应结果
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
//发送响应请求
$response->send();
//终止Kernel
$kernel->terminate($request, $response);
注册加载对我们得源码解读无实际研究意义,因此本次跳过自动加载composer包。
创建应用程序/服务容器
<?php
//实例化app对象,主要进行一些应用的基础配置
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
//注册应用http请求Kernel对象,处理请求
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
//同上,注册应用命令行Kernel对象
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
//注册用用错误处理
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
return $app;
- 实例化lluminate\Foundation\Application(实例化app对象)
<?php
namespace Illuminate\Foundation;
use Illuminate\Container\Container;
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class Application extends Container implements ApplicationContract, HttpKernelInterface
{
/**
* The base path for the Laravel installation.
*
* @var string
*/
protected $basePath;
public function __construct($basePath = null)
{
//设置基础路径
if ($basePath) {
$this->setBasePath($basePath);
}
$this->registerBaseBindings();
//注册基础服务提供者 事件服务、日志服务、路由服务
$this->registerBaseServiceProviders();
//注册容器别名,即我们常用的通过 app('redis') 获取redis实例
$this->registerCoreContainerAliases();
}
//设置基础路径
public function setBasePath($basePath)
{
$this->basePath = rtrim($basePath, '\/');
//绑定应用的基础路径到容器中
$this->bindPathsInContainer();
return $this;
}
//绑定应用的基础路径到容器中
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());//引导目录
}
//注册基础服务提供者 事件服务、日志服务、路由服务
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this));
$this->register(new LogServiceProvider($this));
$this->register(new RoutingServiceProvider($this));
}
//注册容器别名
public function registerCoreContainerAliases()
{
foreach ([
'app' => [self::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, \Psr\SimpleCache\CacheInterface::class],
'cache.psr6' => [\Symfony\Component\Cache\Adapter\Psr16Adapter::class, \Symfony\Component\Cache\Adapter\AdapterInterface::class, \Psr\Cache\CacheItemPoolInterface::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, \Illuminate\Database\ConnectionResolverInterface::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],
'redis.connection' => [\Illuminate\Redis\Connections\Connection::class, \Illuminate\Contracts\Redis\Connection::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);
}
}
}
}
内核绑定(实际上解析App\Http\Kernel)
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
//代码略,实际我们看继承的Illuminate\Foundation\Http\Kernel构造方法
}
<?php
namespace Illuminate\Foundation\Http;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Http\Kernel as KernelContract;
use Illuminate\Routing\Router;
class Kernel implements KernelContract
{
public function __construct(Application $app, Router $router)
{
$this->app = $app;
$this->router = $router;
//加载中间件、组合中间件
$this->syncMiddlewareToRouter();
}
protected function syncMiddlewareToRouter()
{
//中间件加载顺序,App\Http\Kernel对象重写middlewarePriority,可调整加载顺序
$this->router->middlewarePriority = $this->middlewarePriority;
//注册中间件分组
foreach ($this->middlewareGroups as $key => $middleware) {
$this->router->middlewareGroup($key, $middleware);
}
//注册中间件别名
foreach ($this->routeMiddleware as $key => $middleware) {
$this->router->aliasMiddleware($key, $middleware);
}
}
}
捕获请求 (与路由相关,同样的,我们直接看Illuminate\Contracts\Http\Kernel)
<?php
namespace Illuminate\Foundation\Http;
use Illuminate\Contracts\Http\Kernel as KernelContract;
class Kernel implements KernelContract
{
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,//加载环境变量配置
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,//加载基本配置
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,//加载错误&异常处理
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,//清除已解析的Facade并重新启动,注册config文件中alias定义的所有Facade类到容器
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,//注册config中providers定义的所有Providers类到容器
\Illuminate\Foundation\Bootstrap\BootProviders::class,//调用所有已注册Providers的boot方法
];
//请求处理
public function handle($request)
{
try {
//启用方法欺骗,比如允许post表单模拟put、delete、patch请求
$request->enableHttpMethodParameterOverride();
//处理请求并返回响应结果
$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);
}
$this->app['events']->dispatch(
new RequestHandled($request, $response)
);
return $response;
}
protected function sendRequestThroughRouter($request)
{
//将request绑定到app容器中
$this->app->instance('request', $request);
//清除已经解析的request门面实例
Facade::clearResolvedInstance('request');
//初始化项目
$this->bootstrap();
//路由调度,通过dispatchToRouter将请求映射到路由
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
$this->app->bootstrapWith($this->bootstrappers());
}
}
protected function bootstrappers()
{
//以上代码中可以看到
return $this->bootstrappers;
}
//路由分配
protected function dispatchToRouter()
{
return function ($request) {
$this->app->instance('request', $request);
return $this->router->dispatch($request);
};
}
}
- 路由分配
<?php
namespace Illuminate\Routing;
/**
* @mixin \Illuminate\Routing\RouteRegistrar
*/
class Router implements BindingRegistrar, RegistrarContract
{
//路由分配
public function dispatch(Request $request)
{
$this->currentRequest = $request;
return $this->dispatchToRoute($request);
}
/**
* 通过路由分配请求,并返回响应结果
*
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function dispatchToRoute(Request $request)
{
return $this->runRoute($request, $this->findRoute($request));
}
/**
* 查找路由并匹配请求
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Routing\Route
*/
protected function findRoute($request)
{
$this->current = $route = $this->routes->match($request);
$this->container->instance(Route::class, $route);
return $route;
}
}
总结:源码分析是相对于枯燥,对源码的分析主要在于了解他的原理,设计思想等等,大致的实现方法,总结出来,再进行更加细致化的分析,本次先着手入口文件分析,后续如有更深入的研究,会持续更新。