源码分析---入口源码分析全局配置加载类全局配置类的主要代码如下:classConfig{/***@var数组配置参数*/私人静态$配置=[];/***@var字符串参数范围*/privatestatic$range='_sys_';/***设置配置参数范围*@accesspublic*@paramstring$rangescope*@returnvoid*/publicstaticfunctionrange($range){....}/***解析配置文件或内容*@accesspublic*@paramstring$config配置文件路径或内容*@paramstring$type配置解析类型*@paramstring$name配置名称(如果设置则表示二级配置)*@paramstring$rangescope*@returnmixed*/publicstaticfunctionparse($config,$type='',$name='',$range=''){....}/***加载配置文件(PHP格式)*@accesspublic*@paramstring$file配置文件名*@paramstring$name配置名(如果设置了表示二级配置)*@paramstring$rangescope*@returnmixed*/publicstaticfunctionload($file,$name='',$范围=''){....}/***检测配置是否存在*@accesspublic*@paramstring$name配置参数名(支持二次配置。编号拆分)*@paramstring$rangescope*@returnbool*/publicstaticfunctionhas($name,$range=''){....}/***如果配置参数为空则获取所有配置*@accesspublic*@paramstring$name配置参数名(支持二次配置分隔by.)*@paramstring$rangescope*@returnmixed*/publicstaticfunctionget($name=null,$range=''){....}/***将配置参数名称设置为数组是批量设置*@accesspublic*@paramstring|array$name配置参数名(支持二次配置。编号拆分)*@parammixed$value配置值*@paramstring$rangescope*@returnmixed*/publicstaticfunctionset($name,$value=null,$range=''){....}/***重置配置参数*@accesspublic*@paramstring$rangescope*@returnvoid*/publicstaticfunctionreset($range=''){....}}添加配置添加配置使用thinkConfig::set($name,$value=null,$range='')方法;$name为字符串时,value为要设置的值,$name为数组时,批量设置配置/***如果配置参数名是数组,则为批量设置*@accesspublic*@paramstring|array$name配置参数名(支持二次配置。编号拆分)*@parammixed$value配置值*@paramstring$rangescope*@returnmixed*/publicstaticfunctionset($name,$value=null,$range=''){$range=$range?:self::$range;如果(!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);自我::$config[$range][strtolower($name[0])][$name[1]]=$value;}返回值;}//数组表示批量设置if(is_array($name)){if(!empty($value)){self::$config[$range][$value]=isset(self::$config[$range][$价值])?到达ay_merge(self::$config[$range][$value],$name):$name;返回自我::$配置[$范围][$值];}returnself::$config[$range]=array_merge(self::$config[$range],array_change_key_case($name));}//如果为空,直接返回已有的配置returnself::$config[$range];}设置配置的时候主要有两种情况:1.$name是一个字符串2.$name是一个二维数组(目前只支持二维数组)。配置首先会确定配置的范围。如果没有设置,则使用默认的_sys_scope,判断scope是否存在,会初始化为数组。对于$name的两种不同形式的参数,处理方式不同。$name为字符串形式。//字符串表示单个配置设置if(is_string($name)){if(!strpos($name,'.')){self::$config[$range][strtolower($name)]=$价值;}else{//二维数组$name=explode('.',$name,2);self::$config[$range][strtolower($name[0])][$name[1]]=$value;}返回值;,不直接使用$name的小写形式作为key,在配置(self::$config)中设置$value为value。如果。包含,只处理前两项,即把字符串按.分割成一个数组。对于前两项,将$value设置为配置。$name是数组的形式//数组表示批量设置if(is_array($name)){if(!empty($value)){self::$config[$range][$value]=isset(自我::$config[$range][$value])?array_merge(self::$config[$range][$value],$name):$name;返回自我::$配置[$范围][$值];}returnself::$config[$range]=array_merge(self::$config[$range],array_change_key_case($name));}如果设置了$value的值,则使用$value作为配置键,然后将$name的配置设置为配置(如果已经有值,则数组合并将原值替换为传入的值,如果没有值,直接赋值),如果没有设置$value的值,则把每一项都设置在这个scope下。备注:array_change_key_case($array,[int$case=CASE_LOWER]):array设置数组的键为大写或小写,默认为小写。获取配置看完上面的分析,你应该对获取配置有了一个大概的了解,也就是设置配置的逆过程。/***配置参数为空时获取所有配置*@accesspublic*@paramstring$name配置参数名(支持二级配置。编号拆分)*@paramstring$rangescope*@returnmixed*/publicstatic函数get($name=null,$range=''){$range=$range?:self::$range;//没有参数时获取所有if(empty($name)&&isset(self::$config[$range])){returnself::$config[$range];}//非二级配置直接返回if(!strpos($name,'.')){$name=strtolower($name);返回isset(self::$config[$range][$name])?自我::$配置[$范围][$名称]:空;}//二维数组设置和获取支持$name=explode('.',$name,2);$name[0]=strtolower($name[0]);if(!isset(self::$config[$range][$name[0]])){//动态加载额外配置$module=Request::instance()->module();$文件=配置路径。($module?$module.DS:'')。'额外的'。DS。$名字[0]。CONF_EXT;is_file($文件)&&self::load($file,$name[0]);}返回isset(self::$config[$range][$name[0]][$name[1]])?self::$config[$range][$name[0]][$name[1]]:null;}看完代码,你应该已经理解了无参数获取和非二次获取。二维数组有一点需要注意,它会动态加载额外的配置$module=Request::instance()->module();该方法的实现如下:/***设置或获取当前模块名*@accesspublic*@paramstring$module模块名*@returnstring|Request*/publicfunctionmodule($module=null){如果(!is_null($module)){$this->module=$module;返回$这个;}else{return$this->module?:'';}}该方法是获取当前请求的模块。//二维数组处理逻辑if(!isset(self::$config[$range][$name[0]])){//动态加载附加配置$module=Request::instance()->module();$文件=配置路径。($module?$module.DS:'')。'额外的'。DS。$名字[0]。CONF_EXT;is_file($file)&&self::load($file,$name[0]);}返回isset(self::$config[$range][$name[0]][$name[1]])?自我::$配置[$范围][$名称[0]][$名称[1]]:空;从代码中可以看出,通过request获取当前访问的模块,判断当前模块或配置目录下extra目录是否一直存在。如果文件存在则加载,然后返回,动态加载通过thinkConfig::load($file)加载。/***加载配置文件(PHP格式)*@accesspublic*@paramstring$file配置文件名*@paramstring$name配置名(如果设置,表示二级配置)*@paramstring$rangescope*@返回混合*/publicstaticfunctionload($file,$name='',$range=''){$range=$range?:self::$range;如果(!isset(self::$config[$range]))self::$config[$range]=[];如果(is_file($file)){$name=strtolower($name);$type=pathinfo($file,PATHINFO_EXTENSION);if('php'==$type){returnself::set(include$file,$name,$range);}if('yaml'==$type&&function_exists('yaml_parse_file')){returnself::set(yaml_parse_file($file),$name,$range);}returnself::parse($file,$type,$name,$range);}returnself::$config[$range];}加载的配置方法主要逻辑是处理php、yaml、ini、json、xml格式的配置。php类型可以直接include然后设置configure,而yaml则通过yaml_parse_file方法解析成数据然后设置configure。其他的都是固定驱动解析,业务逻辑在thinkConfig::parse()方法中。/***解析配置文件或内容*@accesspublic*@paramstring$config配置文件路径或内容*@paramstring$type配置解析类型*@paramstring$name配置名称(如果设置则表示二级配置)*@paramstring$rangescope*@returnmixed*/publicstaticfunctionparse($config,$type='',$name='',$range=''){$range=$range?:self:::$范围;如果(empty($type))$type=pathinfo($config,PATHINFO_EXTENSION);$class=false!==strpos($type,'\\')?$type:'\\think\\config\\driver\\'.ucwords($type);返回self::set((new$class())->parse($config),$name,$range);}通过pathinfo()方法获取Path信息,设置第二个参数返回扩展名,判断扩展名中是否有\,如果有则输入的是类。通过类的parse方法直接解析配置。如果是文件扩展名,则通过\\think\\config\\driver\\下对应的驱动解析配置,然后设置到配置中。总结一下,thinkphp的配置加载方式主要有两种,1.加载框架内部的预设配置2.动态加载用户配置对于第一种方式,由于默认配置是PHP类型的,直接通过set方法,第二种方式是使用load方法判断文件的扩展名来进行不同的驱动分析。其中php、yaml可以直接解析成数组,而xml、json、ini则通过相应的驱动解析然后设置。配置后,会通过调用parse方法自动判断扩展名,然后进行解析。至于Config类中的其他方法比较简单,可以直接查看代码获取相关信息。
