• 深入理解 Laravel 中 config 配置加载原理


    Laravel的配置加载其实就是加载config目录下所有文件配置。如何过使用php artisan config:cache则会把加载的配置合并到一个配置文件中,下次请求就不会再去加载config目录。

    1.加载流程

    1. LoadEnvironmentVariables .env环境配置加载。如果缓存配置是不会加载.env
    2. LoadConfiguration 判断是否缓存配置
    3. 是,则直接加载配置,不会加载config目录所有文件了
    4. 否,则加载config目录所有PHP文件

    2.什么时候加载配置?

    内核启动的时候。加载以下启动类

    \Illuminate\Foundation\Http\Kernel

    protected $bootstrappers = [
            \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,  // 加载 .env
            \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, // 加载config配置
            ...
        ];

    本文重点讲解第二个config配置加载。第一个请查看 深入理解 Laravel 中.env 文件读取

    3. 源码分析

    LoadConfiguration类中config配置加载的具体逻辑。

    其实就是判断缓存是否存在,存在则加载,不存在则递归遍历config目录所有php文件。如果运行php artisan config:cache,则会把加载结果保存在bootstrap/cache目录中;你可能还会看到services.php文件,这是一个保存所有的服务提供者的文件,具体以后会讲。

    public function bootstrap(Application $app)
        {
            $items = [];
    
           // 首先,我们将看看是否有缓存配置文件。 如果是,我们将从该文件加载配置项,因此它非常快。 
           // 否则,我们需要遍历每个配置文件并加载它们。
            if (file_exists($cached = $app->getCachedConfigPath())) {
                // 加载缓存的配置文件
                $items = require $cached;
    
                $loadedFromCache = true;
            }
    
            // 接下来,我们将遍历配置目录中的所有配置文件,并将每个配置文件加载到Repository中。
            // 这将使开发人员可以使用所有选项,以便在此应用程序的各个部分中使用。
            $app->instance('config', $config = new Repository($items));
    
            // 如果没有缓存配置才会去加载config目录
            if (! isset($loadedFromCache)) {
                // 加载config目录所有PHP文件
                $this->loadConfigurationFiles($app, $config);
            }
    
            //最后,我们将根据加载的配置值设置应用程序的环境。 
            // 我们将传递一个回调,该回调将用于在Web环境中获取环境,其中不存在“--env”开关。
            $app->detectEnvironment(function () use ($config) {
                return $config->get('app.env', 'production');
            });
    
            // 设置时区
            date_default_timezone_set($config->get('app.timezone', 'UTC'));
    
            mb_internal_encoding('UTF-8');
        }
    
        /**
         * 从所有文件加载配置项。因此效率很低
         *
         * @param  \Illuminate\Contracts\Foundation\Application  $app
         * @param  \Illuminate\Contracts\Config\Repository  $repository
         * @return void
         * @throws \Exception
         */
        protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
        {
            // 遍历出所有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);
            }
        }

    4.小结与注意点

    1. php artisan config:cache之后不会加载config配置,即便你修改了config目录中的配置文件也是不生效的,除非清除缓存php artisna config:clear,或者重新缓存 php artisan config:cache
    2. 因为配置缓存可以提高效率,因此推荐生产环境使用配置缓存。
    3. 不能在config目录内定义配置以外的东西。比如在config目录内定义类,定义常量,自定义函数。这些都是不推荐的,因为配置缓存之后,config目录任何文件都不会加载,这些类或者常量不存在,最终导致自动加载失败。解决方案是使用composer.json的自动加载配置来加载:
    "autoload": {
            "classmap": [
                "database/seeds",
                "database/factories"
            ],
            "psr-4": {
                "App\\": "app/"
            },
            "files": [
                # 这样那个会加载helpers.php文件了。该文件定义的是辅助函数
                "bootstrap/helpers.php"
            ]
        },
    1. 在 config 中调用其他的 config('something.item') 是不会预期的加载的。因为不能保证配置something.item已经加载到了
  • 相关阅读:
    MTK 定时器 休眠时的动作
    Troubleshooting MySQL Memory Usage
    disruptor
    Google Protocol Buffer 的使用和原理
    百度贴吧10亿量级LAMP架构分享
    nginx 不带www到www域名的重定向
    配置电信网通双线双IP的解决办法
    Create a W3C validated anchor link with target=“_blank”
    Could not update ICEauthority file /home/username/.ICEauthority
    Can't load IA 32bit .dll on a AMD 64bit platform
  • 原文地址:https://www.cnblogs.com/lxwphp/p/15453477.html
Copyright © 2020-2023  润新知