AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
Config类的作用:用于加载各种配置文件,配置文件一般叫config.php,里面就是一个数组; 这个配置参数数组的结构是: ``` $config = [ '作用域一':[ '一级配置':'值', '一级配置':[ '二级配置':'值' ] ] ]; ``` `<?php` `namespace think;` ``` class Config { ``` ``` /** * @var array 配置参数 */ private static $config = []; /** * @var string 参数作用域 */ private static $range = '_sys_'; ``` 存储配置参数的数组: `private static $config = [];` 作用域静态变量 `private static $range = '_sys_';` **设置作用域range():** TP默认的作用域名称是_sys_,表示系统作用域,实际使用中,几乎不会用到这个函数; 除非你真的需要创建一个独立作用域,与_sys_处于同一级,不然都是在_sys_下面创一个自定义下标的数组就是了. 一旦你切换了作用域,那么整个系统的参数就完全不一样了,这种情况很危险,很容易出错.除非你非常确定你切换了作用域后,你的配置参数没有问题. ``` /** * 设定配置参数的作用域 * @access public * @param string $range 作用域 * @return void */ public static function range($range) { self::$range = $range; if (!isset(self::$config[$range])) self::$config[$range] = []; } ``` **加载配置文件load():** load()函数用于加载配置文件,把文件里面的配置参数放到参数数组中; ``` /** * 加载配置文件(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); //pathinfo — 返回文件路径的信息 : https://www.php.net/manual/zh/function.pathinfo.php //这里指定了返回文件类型名称,一般是php $type = pathinfo($file, PATHINFO_EXTENSION); if ('php' == $type) { //include 表达式包含并运行指定文件。: https://www.php.net/manual/zh/function.include.php //这里的结果就是运行file,而file是返回一个数组,也就是把这个数组作为参数传过去了 return self::set(include $file, $name, $range); } //也支持yaml类型的配置文件,但是实际上没见过有人用... //YAML 教程: https://www.ruanyifeng.com/blog/2016/07/yaml.html if ('yaml' == $type && function_exists('yaml_parse_file')) { //yaml_parse_file — Parse a YAML stream from a file :https://www.php.net/manual/zh/function.yaml-parse-file.php return self::set(yaml_parse_file($file), $name, $range); } //如果是其他类型的文件,则使用自定义的解析函数进行解析 return self::parse($file, $type, $name, $range); } return self::$config[$range]; } ``` **自定义的解析配置文件的函数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); //strpos — 查找字符串首次出现的位置 :https://www.php.net/manual/zh/function.strpos.php //如果文件类型字符串中含有\\,就认为是在指定使用某个配置解析引擎 $class = false !== strpos($type, '\\') ? $type : '\\think\\config\\driver\\' . ucwords($type); //ucwords — 将字符串中每个单词的首字母转换为大写 //TP内置有Ini ,Json ,Xml 3中配置解析引擎,如果你真的有能力自己创造出一种配置格式,也可以写自己的解析引擎,但实际上没人会这样做 //这里new $class(),因为class的值刚好就是指向解析引擎的位置 return self::set((new $class())->parse($config), $name, $range); } ``` 这里顺便看一下TP内置的几个配置解析引擎,内容很简单,就是只有一个解析函数parse(),然后返回解析出来后的内容, Ini文件类型 ``` namespace think\config\driver; class Ini { //config可以是文件或者字符串,最终都会解析成数组返回 public function parse($config) { if (is_file($config)) { //parse_ini_file() 载入一个由 filename 指定的 ini 文件,并将其中的设置作为一个联合数组返回。 return parse_ini_file($config, true); } else { //parse_ini_string() 返回 ini 字符串解析后的关联数组 return parse_ini_string($config, true); } } } ``` Jason文件类型 ``` namespace think\config\driver; class Json { public function parse($config) { if (is_file($config)) { $config = file_get_contents($config); } //json_decode — 对 JSON 格式的字符串进行解码,接受一个 JSON 编码的字符串并且把它转换为 PHP 变量 //这里第二个参数为 true 时,将强制返回 array 而非 object 。 $result = json_decode($config, true); return $result; } } ``` Xml文件类型 ``` namespace think\config\driver; class Xml { public function parse($config) { if (is_file($config)) { //simplexml_load_file — Interprets an XML file into an object //解析一个xml文件为一个对象 $content = simplexml_load_file($config); } else { //simplexml_load_string — Interprets a string of XML into an object //解析一个字符串为一个对象 $content = simplexml_load_string($config); } //把对象强制转为数组 $result = (array) $content; foreach ($result as $key => $val) { if (is_object($val)) { //TP框架配置参数数组只支持三维,第一维是作用域,所以自己定义配置参数的时候最多只能是二维数组 //如果你定义成3维,框架就不管的了 $result[$key] = (array) $val; } } return $result; } } ``` **检查一个配置是否存在has():** ``` /** * 检测配置是否存在 * @access public * @param string $name 配置参数名(支持二级配置 . 号分割) * @param string $range 作用域 * @return bool */ public static function has($name, $range = '') { $range = $range ?: self::$range; if (!strpos($name, '.')) { //参数值不存在 . 号,就直接获取对应名称的值 return isset(self::$config[$range][strtolower($name)]); } //否则认为是二维数组,TP参数在作用域下只支持2层,你传2个点过来也没用,会忽略掉 $name = explode('.', $name, 2); return isset(self::$config[$range][strtolower($name[0])][$name[1]]); } ``` **获取配置参数get():** 获取指定的参数的值,可以触发加载额外配置文件,可以在应用目录和每个模块目录里面创建extra目录存放额外配置文件; 如果是要获取二级配置,可以用 . 符号来分割层级,例:Config::get('app.id'); 表示获取当前域里面的app 组 里面的id 的值 ``` /** * 获取配置参数 为空则获取所有配置 * @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; } // 二维数组设置和获取支持,TP只支持2级配置,所以explode有第三个参数为2,返回2个元素,最后那个元素包括了剩余的全部内容 //https://www.php.net/manual/zh/function.explode.php $name = explode('.', $name, 2); $name[0] = strtolower($name[0]); //如果不存在这个配置参数,就去找额外配置文件,并加载进来 if (!isset(self::$config[$range][$name[0]])) { // 动态载入额外配置 $module = Request::instance()->module(); //这个额外配置目录必须命名为"extra",可以在每个模块中分别创建这个目录 //这个额外配置文件,必须返回一个二维数组.因为前面是已经确认是要获取第二级参数,并且没有人会为了返回一个字符串而专门创建一个文件吧. $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; } ``` **设置配置参数set():** 1直接配置一级配置: Config::set('email','123@123.com'); 2:直接配置二级配置:Config::set('my.email','123@123.com'); 3:批量配置:Config::set($arr,'my'); ,my是组名,不是配置的值; ``` /** * 设置配置参数 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; } // 数组则表示批量设置 //如果$name是数组的情况下$value有值,则把这个数组放到$value组里面 if (is_array($name)) { //注意这里:本来$name参数是组名,但如果是数组,那么$value就变成组名.相当于把两个参数的意义调转了.所以有时候会发现代码参数位置写反了,其实没有写错! if (!empty($value)) { //array_merge — 合并一个或多个数组 https://www.php.net/manual/zh/function.array-merge.php //如果输入的数组中有相同的字符串键名,则该键名后面的值将覆盖前一个值。然而,如果数组包含数字键名,后面的值将 不会 覆盖原来的值,而是附加到后面。 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]; } ``` **重置配置参数reset():** 用于将整个 或者某个域 的配置参数清空,这个方法几乎不会用到; 参数是 true ,则清空整个配置数组, 如果是域名称,就清空这个域的配置数据; ``` /** * 重置配置参数 * @access public * @param string $range 作用域 * @return void */ public static function reset($range = '') { $range = $range ?: self::$range; //如果是true ,才确认清空整个配置数组 if (true === $range) { self::$config = []; } else { //清空对应名称的域里面的配置 self::$config[$range] = []; } } ```