源码分析(五)—配置篇

栏目: 编程工具 · 发布时间: 5年前

内容简介:全局配置类的主要代码如下:添加配置用的是thinkConfig::set($name, $value = null, $range = '')方法;当$name是字符串时候value是要设置的值,$name为数组时候,批量设置配置。设置配置时候主要分了两种情况:

源码分析---入口篇

源码分析

全局配置加载类

全局配置类的主要代码如下:

class Config
{
    /**
     * @var array 配置参数
     */
    private static $config = [];

    /**
     * @var string 参数作用域
     */
    private static $range = '_sys_';

    /**
     * 设定配置参数的作用域
     * @access public
     * @param  string $range 作用域
     * @return void
     */
    public static function range($range)
    {
       ....
    }

    /**
     * 解析配置文件或内容
     * @access public
     * @param  string $config 配置文件路径或内容
     * @param  string $type   配置解析类型
     * @param  string $name   配置名(如设置即表示二级配置)
     * @param  string $range  作用域
     * @return mixed
     */
    public static function parse($config, $type = '', $name = '', $range = '')
    {
        ....
    }

    /**
     * 加载配置文件(PHP格式)
     * @access public
     * @param  string $file  配置文件名
     * @param  string $name  配置名(如设置即表示二级配置)
     * @param  string $range 作用域
     * @return mixed
     */
    public static function load($file, $name = '', $range = '')
    {
        ....
    }

    /**
     * 检测配置是否存在
     * @access public
     * @param  string $name 配置参数名(支持二级配置 . 号分割)
     * @param  string $range  作用域
     * @return bool
     */
    public static function has($name, $range = '')
    {
        ....
    }

    /**
     * 获取配置参数 为空则获取所有配置
     * @access public
     * @param  string $name 配置参数名(支持二级配置 . 号分割)
     * @param  string $range  作用域
     * @return mixed
     */
    public static function get($name = null, $range = '')
    {
        ....
    }

    /**
     * 设置配置参数 name 为数组则为批量设置
     * @access public
     * @param  string|array $name  配置参数名(支持二级配置 . 号分割)
     * @param  mixed        $value 配置值
     * @param  string       $range 作用域
     * @return mixed
     */
    public static function set($name, $value = null, $range = '')
    {
        ....
    }

    /**
     * 重置配置参数
     * @access public
     * @param  string $range 作用域
     * @return void
     */
    public static function reset($range = '')
    {
        ....
    }
}

添加配置

添加配置用的是thinkConfig::set($name, $value = null, $range = '')方法;当$name是字符串时候value是要设置的值,$name为数组时候,批量设置配置。

/**
     * 设置配置参数 name 为数组则为批量设置
     * @access public
     * @param  string|array $name  配置参数名(支持二级配置 . 号分割)
     * @param  mixed        $value 配置值
     * @param  string       $range 作用域
     * @return mixed
     */
    public static function set($name, $value = null, $range = '')
    {
        $range = $range ?: self::$range;

        if (!isset(self::$config[$range])) self::$config[$range] = [];

        // 字符串则表示单个配置设置
        if (is_string($name)) {
            if (!strpos($name, '.')) {
                self::$config[$range][strtolower($name)] = $value;
            } else {
                // 二维数组
                $name = explode('.', $name, 2);
                self::$config[$range][strtolower($name[0])][$name[1]] = $value;
            }

            return $value;
        }

        // 数组则表示批量设置
        if (is_array($name)) {
            if (!empty($value)) {
                self::$config[$range][$value] = isset(self::$config[$range][$value]) ?
                    array_merge(self::$config[$range][$value], $name) :
                    $name;

                return self::$config[$range][$value];
            }

            return self::$config[$range] = array_merge(
                self::$config[$range], array_change_key_case($name)
            );
        }

        // 为空直接返回已有配置
        return self::$config[$range];
    }

设置配置时候主要分了两种情况:

1. $name是字符串
2. $name是二维数组(目前只支持二维数组)

配置会先判断配置的作用域,不设置就用默认的 _sys_ 作用域,并且判断该作用域是否存在,不存在就初始化为数组。对于$name这两种不同形式的参数,处理方式也不一样,

$name为字符串形式

// 字符串则表示单个配置设置
    if (is_string($name)) {
        if (!strpos($name, '.')) {
            self::$config[$range][strtolower($name)] = $value;
        } else {
            // 二维数组
            $name = explode('.', $name, 2);
            self::$config[$range][strtolower($name[0])][$name[1]] = $value;
        }

        return $value;
    }

判断字符串中是否带 . , 没有直接把$name的小写形式作为key,$value作为值设置到配置(self::$config)中.

如果带 . ,只处理前面两项,即把字符串通过 . 分割成数组,取数组的前面两项,把$value设置到配置中。

$name为数组形式

// 数组则表示批量设置
    if (is_array($name)) {
        if (!empty($value)) {
            self::$config[$range][$value] = isset(self::$config[$range][$value]) ?
                array_merge(self::$config[$range][$value], $name) :
                $name;

            return self::$config[$range][$value];
        }

        return self::$config[$range] = array_merge(
            self::$config[$range], array_change_key_case($name)
        );
    }

如果设置了$value的值,那么把$value作为配置的键,再把$name的配置设置到配置中(如果原来已经有值,数组合并用传入的值替换原来的值,如果原来没有值,直接赋值),如果没有设置$value的值,那么把数组的每一项设置到该作用域下。

备注: array_change_key_case( $array, [ int $case = CASE_LOWER ] ) : array 把数组的键设置为大写或小写,默认是小写。

获取配置

看完了上面的分析,对于获取配置应该也有了一个大致的思路了,就是设置配置的反向。

/**
     * 获取配置参数 为空则获取所有配置
     * @access public
     * @param  string $name 配置参数名(支持二级配置 . 号分割)
     * @param  string $range  作用域
     * @return mixed
     */
    public static function get($name = null, $range = '')
    {
        $range = $range ?: self::$range;

        // 无参数时获取所有
        if (empty($name) && isset(self::$config[$range])) {
            return self::$config[$range];
        }

        // 非二级配置时直接返回
        if (!strpos($name, '.')) {
            $name = strtolower($name);
            return isset(self::$config[$range][$name]) ? self::$config[$range][$name] : null;
        }

        // 二维数组设置和获取支持
        $name    = explode('.', $name, 2);
        $name[0] = strtolower($name[0]);

        if (!isset(self::$config[$range][$name[0]])) {
            // 动态载入额外配置
            $module = Request::instance()->module();
            $file   = CONF_PATH . ($module ? $module . DS : '') . 'extra' . DS . $name[0] . CONF_EXT;

            is_file($file) && self::load($file, $name[0]);
        }

        return isset(self::$config[$range][$name[0]][$name[1]]) ?
            self::$config[$range][$name[0]][$name[1]] :
            null;
    }

看了代码,应该对于无参获取和非二级获取已经懂了,那二维数组有个需要注意的地方,就是会动态加载额外的配置。

$module = Request::instance()->module();

该方法的实现如下:

/**
     * 设置或者获取当前的模块名
     * @access public
     * @param string $module 模块名
     * @return string|Request
     */
    public function module($module = null)
    {
        if (!is_null($module)) {
            $this->module = $module;
            return $this;
        } else {
            return $this->module ?: '';
        }
    }

该方法就是获取当前请求的模块。

//二维数组处理逻辑
    if (!isset(self::$config[$range][$name[0]])) {
        // 动态载入额外配置
        $module = Request::instance()->module();
        $file   = CONF_PATH . ($module ? $module . DS : '') . 'extra' . DS . $name[0] . CONF_EXT;
    
        is_file($file) && self::load($file, $name[0]);
    }
    
    return isset(self::$config[$range][$name[0]][$name[1]]) ?
        self::$config[$range][$name[0]][$name[1]] :
        null;

从代码中可以看出,通过request获取到当前访问的模块,判断当前模块中的或者配置目录中的extra目录总是否存在以为数组中键为名字的配置文件,存在就加载进来,再进行返回,动态加载通过thinkConfig::load($file)来进行加载。

/**
     * 加载配置文件(PHP格式)
     * @access public
     * @param  string $file  配置文件名
     * @param  string $name  配置名(如设置即表示二级配置)
     * @param  string $range 作用域
     * @return mixed
     */
    public static function load($file, $name = '', $range = '')
    {
        $range = $range ?: self::$range;

        if (!isset(self::$config[$range])) self::$config[$range] = [];

        if (is_file($file)) {
            $name = strtolower($name);
            $type = pathinfo($file, PATHINFO_EXTENSION);

            if ('php' == $type) {
                return self::set(include $file, $name, $range);
            }

            if ('yaml' == $type && function_exists('yaml_parse_file')) {
                return self::set(yaml_parse_file($file), $name, $range);
            }

            return self::parse($file, $type, $name, $range);
        }

        return self::$config[$range];
    }

该加载配置的方法主要的逻辑是处理php,yaml,ini,json,xml格式的配置。

php类型的是直接include再set配置即可,yaml则是通过yaml_parse_file方法解析成数据再set配置。其他的通过固定的驱动来解析,业务逻辑再thinkConfig::parse()方法中。

/**
     * 解析配置文件或内容
     * @access public
     * @param  string $config 配置文件路径或内容
     * @param  string $type   配置解析类型
     * @param  string $name   配置名(如设置即表示二级配置)
     * @param  string $range  作用域
     * @return mixed
     */
    public static function parse($config, $type = '', $name = '', $range = '')
    {
        $range = $range ?: self::$range;

        if (empty($type)) $type = pathinfo($config, PATHINFO_EXTENSION);

        $class = false !== strpos($type, '\\') ?
            $type :
            '\\think\\config\\driver\\' . ucwords($type);

        return self::set((new $class())->parse($config), $name, $range);
    }

通过pathinfo()方法获取到路径信息, 第二个参数设置返回扩展名,判断扩展名中是否带有 \ 如果有即传入的是一个类。直接通过类的parse方法解析配置,如果是一个文件扩展名称,即通过 \\think\\config\\driver\\ 下对应的驱动来解析配置,再set到配置中。

总结

thinkphp中主要的配置加载方式有两种,

1.加载框架内部预设的配置
2.动态加载用户配置

对于第一中方式,由于默认的配置是 php 类型的,是直接通过set方法执行配置的,第二中方式是通过load方法,判断文件的扩展名来进行不同的驱动解析,其中php和yaml有直接的方式可以解析成数组,xml,json,ini则是通过对应的驱动来解析再set配置的,通过调用parse方法自动判断扩展,再进行解析。至于Config类中其他的方法比较简单,可以直接查看代码获取相关信息。


以上所述就是小编给大家介绍的《源码分析(五)—配置篇》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

A Philosophy of Software Design

A Philosophy of Software Design

John Ousterhout / Yaknyam Press / 2018-4-6 / GBP 14.21

This book addresses the topic of software design: how to decompose complex software systems into modules (such as classes and methods) that can be implemented relatively independently. The book first ......一起来看看 《A Philosophy of Software Design》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具