阅读 291
Laravel config源码解读

Laravel config源码解读

这是我参与更文挑战的第1天,活动详情查看:更文挑战

引言

  • config是laravel中很常用的配置获取方法
  • 如果我们能理解其中是怎么运作的,工作中自然更加得心应手
  • 同时也可以加深对laravel框架的理解

1、加载流程

流程.png

2、什么时候加载

index.php

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);
复制代码

内核启动时加载

\Illuminate\Foundation\Http\Kernel

protected $bootstrappers = [
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, //加载env
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, //加载配置文件
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];
    
    
protected function sendRequestThroughRouter($request)
    {
        $this->app->instance('request', $request);

        Facade::clearResolvedInstance('request');

        //主要是这个
        $this->bootstrap();

      .....
    }
    
    
public function bootstrap()
    {
        if (! $this->app->hasBeenBootstrapped()) {
            $this->app->bootstrapWith($this->bootstrappers());
        }
    }

复制代码

app 核心类

Illuminate\Foundation\Application

public function bootstrapWith(array $bootstrappers)
    {
        $this->hasBeenBootstrapped = true;

        foreach ($bootstrappers as $bootstrapper) {
            $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);
            //注册到app容器,并且执行各bootstarp方法
            $this->make($bootstrapper)->bootstrap($this);

            $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
        }
    }
复制代码

3、LoadConfiguration 源码分析

兜兜转转终于到了最核心的加载配置类

\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables

public function bootstrap(Application $app)
    {
        $items = [];

        //检测是否有缓存文件
        if (is_file($cached = $app->getCachedConfigPath())) {
            $items = require $cached;

            $loadedFromCache = true;
        }

        //注册config实例
        //Repository 实际上是实现了ArrayAccess和ConfigContract
        //ArrayAccess允许对象像数组一样访问
        $app->instance('config', $config = new Repository($items));

        //无缓存文件就加载
        if (! isset($loadedFromCache)) {
            $this->loadConfigurationFiles($app, $config);
        }

        //设置app环境变量值
        $app->detectEnvironment(function () use ($config) {
            return $config->get('app.env', 'production');
        });
    }
复制代码

loadConfigurationFiles方法

 protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
    {
        //获取所有config下.php文件
        $files = $this->getConfigurationFiles($app);

        if (! isset($files['app'])) {
            throw new Exception('Unable to load the "app" configuration file.');
        }
        
        foreach ($files as $key => $path) {
            //写入
            $repository->set($key, require $path);
        }
    }
复制代码

getConfigurationFiles

protected function getConfigurationFiles(Application $app)
    {
        $files = [];

        $configPath = realpath($app->configPath());

        foreach (Finder::create()->files()->name('*.php')->in($configPath) as $file) {
            $directory = $this->getNestedDirectory($file, $configPath);

            $files[$directory.basename($file->getRealPath(), '.php')] = $file->getRealPath();
        }

        ksort($files, SORT_NATURAL);

        return $files;
    }
复制代码

4、config命令分析

  • PHP artisan config:cache

Illuminate\Foundation\Console\ConfigCacheCommand

public function handle()
    {
        //执行清除
        $this->call('config:clear');

        $config = $this->getFreshConfiguration();
        $configPath = $this->laravel->getCachedConfigPath();
        //写入缓存文件
        $this->files->put(
            $configPath, '<?php return '.var_export($config, true).';'.PHP_EOL
        );

        //尝试加载缓存文件
        try {
            require $configPath;
        } catch (Throwable $e) {
            $this->files->delete($configPath);

            throw new LogicException('Your configuration files are not serializable.', 0, $e);
        }
        //返回成功
        $this->info('Configuration cached successfully!');
    }
复制代码
  • PHP artisan config:clear

Illuminate\Foundation\Console\ConfigClearCommand

public function handle()
    {
        //直接删除缓存文件
        $this->files->delete($this->laravel->getCachedConfigPath());

        $this->info('Configuration cache cleared!');
    }
复制代码

5、注意点

  1. php artisan config:cache 之后不会加载 config 配置,即便你修改了 config 目录中的配置文件也是不生效的,除非清除缓存 php artisna config:clear,或者重新缓存 php artisan config:cache
  2. config内容不能永久修改

6、结尾

与诸君共勉之,希望对您有所帮助

文章分类
后端
文章标签