我是靠谱客的博主 唠叨热狗,最近开发中收集的这篇文章主要介绍thinkphp5.1 config类和env类源码剖析 set方法简要分为4个场景:总结:在APP类执行初始化加载配置时,主要用到了第一和第二个场景看完set方法,再看到get方法的场景:4.正常获取配置get和set方法均已讲解完毕,目光看到load方法:ENV类刨析查看load,set两个函数代码可知,.env的配置内容 : CONFIG_EXT= .PHP(或者其他后缀,一旦指定后缀,只能加载指定后缀的配置文件)调试代码的方法:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  此章节带领读者来一起阅读config类和env类,这两个类是tp5.1加载配置的核心类,看懂了这两个类以后,再结合app类初始化部分,tp5.1的配置加载规则将一目了然。

  此博客专门介绍这两个类,后续有专门的博客专门介绍tp5.1配置的加载,不过为了更好理解代码,这里也会插入。

  config类代码刨析:

(一)主要成员属性以及构造方法

   

config类是由app容器类加载的,app继承了container类,因此读过容器部分的代码就知道,当config实例化的时候,调用__make函数,将app类中赋值的属性$this->configPath以及$this->configExt注入进config,作为config类初始化的值。相关代码:

先解释下这个函数是干什么的:这段函数就是入口文件执行的run方法的最开头部分:

然后,app类先初始化自己,这样$this->configPath以及$this->configExt就初始化好了,当调用不存在的成员变量:$this->config时就会去实例化config类,并将$this->configPath以及$this->configExt两个属性注入config,初始化config.

初始化完成后,config类最核心的函数以及它的作用如图:

ArrayAccess我在容器的文章讲解了,这里不过多阐述。主要核心函数由图可知。

我们先看set方法:

    /**
     * 设置配置参数 name为数组则为批量设置
     * @access public
     * @param  string|array  $name 配置参数名(支持三级配置 .号分割)  如 配置文件名.键值.下级键值一共三级,支持到二维数组
     * @param  mixed         $value 配置值
     * @return mixed
     */
    public function set($name, $value = null)
    {
        if (is_string($name)) {
            if (false === strpos($name, '.')) {
                $name = $this->prefix . '.' . $name;
            }

            $name = explode('.', $name, 3);   //e.g.   app.debug

            if (count($name) == 2) {    //e.g.  $this->config['app']['debug'] = xxx
                $this->config[strtolower($name[0])][$name[1]] = $value;
            } else {       //e.g.   $this->config['app']['debug']['xxxx'] = xxx
                $this->config[strtolower($name[0])][$name[1]][$name[2]] = $value;
            }

            return $value;
        } elseif (is_array($name)) {
            // 批量设置
            if (!empty($value)) {
                if (isset($this->config[$value])) {
                    $result = array_merge($this->config[$value], $name);      //将同属于app配置文件的配置归类于$this->config['app']下,其他文件的配置也是如此分类
                } else {
                    $result = $name;
                }

                $this->config[$value] = $result;                                 //将同属于app配置文件的配置归类于$this->config['app']下,其他文件的配置也是如此分类
            } else {
                $result = $this->config = array_merge($this->config, $name);      //$this->config->set(include $this->thinkPath . 'convention.php');没有传value,直接将配置文件返回的数组合并
            }
        } else {
            // 为空直接返回 已有配置
            $result = $this->config;
        }

        return $result;
    }

 

set方法简要分为4个场景:

1.初始化惯例配置的时候使用的set方法。这个场景在APP类initialize()方法中,代码如下:

走到此处:

 

2.读取配置文件,配置文件所返回的数组走到第二大分支的逻辑  is_array($name) ,该场景和第一点一样,是同样的逻辑分支,但它执行的地方是此处:

 

3.当$name是字符时,则直接设置。如果不是以xx.xx的形式传入,只有一个name值,则默认加上app前缀,意思是默认给app配置文件添加配置。对应代码:

.e.g    当传入的参数是$name = 'app.name' 和 $value = 'xxxx' 时,则设置,$this->config['app']['debug'] =  xxxx;  $name = explode('.', $name, 3);  语句可知,

最多只能支持设置三维数组。比如:$this->config['app']['debug']['xxx'] =  xxxx; 

 

PS:$this->config['app']['debug']['xxx']数组中存在这样的对应关系,第一维的键对应相应的配置文件,比如  $this->config['app']对应app.php的配置文件。

接下来后面的二维或者到三维数组的元素是该文件下的配置。比如:$this->config['app']['debug']['xxx']  中的['debug']['xxx']是app.php配置文件的某项配置。

所有配置会按照这种形式,以第一维的键对应配置的文件名,归类并对应到各自的文件名键中去,保存在$this->config中。

 

4.最后一个逻辑分支:$name为空时,返回$this->config.

 

总结:在APP类执行初始化加载配置时,主要用到了第一和第二个场景

 

看完set方法,再看到get方法的场景:

代码:

1.没有指定配置文件。

.e.g  比如:app.debug ,你不写app,只写了debug,则函数默认给你加上app,意思是该配置默认为app.xxx

 

2.无参数时,将获取所有保存在属性config中的配置

 

3.获取某配置文件下所有的配置

.e.g    当输入$name为'app.'  ,如果你的获取是这样写的就会执行这一段代码,substr($name, 0, -1)=>将最后的.去掉,比如app. 就变成 app.此时执行pull函数

     /**
     * 获取一级配置
     * @access public
     * @param  string    $name 一级配置名
     * @return array
     */
    public function pull($name)
    {
        $name = strtolower($name);

        if ($this->yaconf) {   //如果yaconf开启
            $yaconfName = $this->getYaconfName($name);

            if (Yaconf::has($yaconfName)) {
                $config = Yaconf::get($yaconfName);
                return isset($this->config[$name]) ? array_merge($this->config[$name], $config) : $config;  //假设name是app,如果yaconf的app有数据,就会把$this->config['app']的东西和yaconf合并返回(相同键的元素,yaconf会覆盖,优先级高)
            }
        }

        return isset($this->config[$name]) ? $this->config[$name] : [];    //假设name是app,直接返回$this->config['app']的内容
    }

ps:如果开启了yaconf,则会将yaconf的内容和当前的的配置合并,相同元素以yaconf为准.   否则,返回config属性所保存的配置

 

4.正常获取配置

.e.g   传入app.debug,就返回app配置文件下debug的配置

 

get和set方法均已讲解完毕,目光看到load方法:

这段代码关联到app类的init()方法:

根据app执行时,config类去加载app类决定执行的对应后缀的配置文件。因此,这里便使用到工厂模式,以用来加载和app类执行的相应后缀的配置文件。

    protected function loadFile($file, $name)
    {
        $name = strtolower($name);
        $type = pathinfo($file, PATHINFO_EXTENSION);   //$type是返回配置文件后缀信息

        if ('php' == $type) {
            return $this->set(include $file, $name);
        } elseif ('yaml' == $type && function_exists('yaml_parse_file')) {
            return $this->set(yaml_parse_file($file), $name);
        }

        return $this->parse($file, $type, $name);
    }


     /**
     * 解析配置文件或内容
     * @access public
     * @param  string    $config 配置文件路径或内容 ,例如这样的 E:phpstudy_proWWWtp5.1configdatabase.php
     * @param  string    $type 配置解析类型
     * @param  string    $name 配置名(如设置即表示二级配置)
     * @return mixed
     */
    public function parse($config, $type = '', $name = '')
    {
        if (empty($type)) {
            $type = pathinfo($config, PATHINFO_EXTENSION);
        }
        //工厂模式
        $object = Loader::factory($type, '\think\config\driver\', $config);

        return $this->set($object->parse(), $name);
    }




工厂的代码内容,可以阅读容器的章节,属于容器创建对象的内容。

总结:config类核心功能可以看前面的图即可。

 

ENV类刨析

env类核心有这几个类:

     /**
     * 读取环境变量定义文件
     * @access public
     * @param  string    $file  环境变量定义文件
     * @return void
     */
    public function load($file)
    {
        $env = parse_ini_file($file, true);
        $this->set($env);
    }

    /**
     * 获取环境变量值
     * @access public
     * @param  string    $name 环境变量名
     * @param  mixed     $default  默认值
     * @return mixed
     */
    public function get($name = null, $default = null, $php_prefix = true)
    {
        //没有指定配置时,全部返回
        if (is_null($name)) {
            return $this->data;
        }

        $name = strtoupper(str_replace('.', '_', $name));

        if (isset($this->data[$name])) {   //var_dump($this->data);
            return $this->data[$name];
        }
//        echo $name;echo "n";
//        var_dump($this->getEnv($name, $default, $php_prefix));
        //若data数组没有,则去系统变量中看看有无数据
        return $this->getEnv($name, $default, $php_prefix);
    }

    //获取系统的环境变量,分php的系统变量或者其他变量
    protected function getEnv($name, $default = null, $php_prefix = true)
    {
        if ($php_prefix) {
            $name = 'PHP_' . $name;
        }

        //内置函数,获取系统环境变量
        $result = getenv($name); // var_dump($result);

        //返回默认的配置
        if (false === $result) {
            return $default;
        }

        if ('false' === $result) {
            $result = false;
        } elseif ('true' === $result) {
            $result = true;
        }

        //系统变量,如果data没保存,则注册到data
        if (!isset($this->data[$name])) {
            $this->data[$name] = $result;
        }

        return $result;
    }

    /**
     * 设置环境变量值
     * @access public
     * @param  string|array  $env   环境变量
     * @param  mixed         $value  值
     * @return void
     */
    public function set($env, $value = null)  //先分析功能,再分析使用场景
    {
        if (is_array($env)) {
            $env = array_change_key_case($env, CASE_UPPER);            //将所有配置数组的键转为大写
                                                                      //this->data 的键值对,THINK_PATH => E:phpstudy_proWWWtp5.1thinkphp  它的格式统一的  so on
            foreach ($env as $key => $val) {
                if (is_array($val)) {
                    foreach ($val as $k => $v) {
                        $this->data[$key . '_' . strtoupper($k)] = $v;       //例如:[APP=>['path'=>'xxxx']],形成格式一样是,两个大写的单词用下划线拼接。它的格式是统一的,同上的键值对形式 THINK_PATH => E:phpstudy_proWWWtp5.1thinkphp
                    }
                } else {
                    $this->data[$key] = $val;    //将env的东西保存到data,THINK_PATH => E:phpstudy_proWWWtp5.1thinkphp
                }
            }
        } else {
            $name = strtoupper(str_replace('.', '_', $env));  //将.改为下划线,然后全部转大写

            $this->data[$name] = $value;
        }
    }

它在app类中关于关联config的执行部分:

流程:

查看load,set两个函数代码可知,.env的配置内容 : CONFIG_EXT= .PHP(或者其他后缀,一旦指定后缀,只能加载指定后缀的配置文件)

调试代码的方法:

1.不停的打断点调试

2.在调用的函数使用php内置函数debug_backtrace查看改函数的调用情况

 

 

 

最后

以上就是唠叨热狗为你收集整理的thinkphp5.1 config类和env类源码剖析 set方法简要分为4个场景:总结:在APP类执行初始化加载配置时,主要用到了第一和第二个场景看完set方法,再看到get方法的场景:4.正常获取配置get和set方法均已讲解完毕,目光看到load方法:ENV类刨析查看load,set两个函数代码可知,.env的配置内容 : CONFIG_EXT= .PHP(或者其他后缀,一旦指定后缀,只能加载指定后缀的配置文件)调试代码的方法:的全部内容,希望文章能够帮你解决thinkphp5.1 config类和env类源码剖析 set方法简要分为4个场景:总结:在APP类执行初始化加载配置时,主要用到了第一和第二个场景看完set方法,再看到get方法的场景:4.正常获取配置get和set方法均已讲解完毕,目光看到load方法:ENV类刨析查看load,set两个函数代码可知,.env的配置内容 : CONFIG_EXT= .PHP(或者其他后缀,一旦指定后缀,只能加载指定后缀的配置文件)调试代码的方法:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部