laravel源码解读之入口文件(一)

入口文件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;
    }
}

总结:源码分析是相对于枯燥,对源码的分析主要在于了解他的原理,设计思想等等,大致的实现方法,总结出来,再进行更加细致化的分析,本次先着手入口文件分析,后续如有更深入的研究,会持续更新。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值