Config::get() 和 config() 行为完全一致,均读取同一缓存数组;TP8.0 禁止动态写配置,仅支持环境变量;Config::pull() 有副作用,config() 不支持;has() 判断 key 是否存在,不关心值。

Config::get() 和 config() 读配置行为完全一致
两者底层都查同一个已加载的配置缓存数组,首次调用后结果就被缓存,后续无论用哪个接口读,返回值都一样。不是“两个不同来源”,而是同一份数据的两种访问方式。
常见错误现象:config('app_debug') 和 Config::get('app_debug') 返回值不一致?基本是调用时机问题——比如在框架初始化完成前就执行了其中一个,而另一个在应用启动后才调用,导致前者读到空或默认值。
- 推荐统一用
config():更短、支持批量读写、无需use think\facade\Config -
Config::get()适合需要明确门面类上下文的场景(如 IDE 提示强依赖、单元测试隔离) - 二者都不支持运行时重载文件变更——改了
config/app.php必须清空runtime/cache/或设'config_cache_on' => false
config() 支持写,Config::set() 在 TP8.0 已被禁用
TP5.1 中两者都允许动态写配置,但 TP8.0 起 config('key', 'value') 会抛出 think\Exception,Config::set() 同样失效。这不是“不推荐”,而是框架层直接拦截并报错。
使用场景:如果你正在升级 TP5.1 → TP8.0,全局搜索 Config::set( 和 config(..., (第三个参数为值)必须全部替换,否则上线即 500。
立即学习“PHP免费学习笔记(深入)”;
- TP8.0 动态配置唯一合规方式是环境变量:
.env里写APP_DEBUG=true,代码中用Env::get('app_debug', false) -
config()的批量写法config(['a'=>1, 'b'=>2])在 TP8.0 同样禁止,不要尝试绕过 - TP5.1 项目若仍用
Config::set(),注意它只影响当前请求内存,重启即丢,不可用于跨请求状态共享
pull() 是 Config::get() 特有,config() 不提供对应功能
Config::pull('app') 会把 app 配置项从缓存中“取出并删除”,后续再 Config::get('app.') 就拿不到——这其实是为模块化加载或配置隔离设计的冷门能力,config() 完全没有这个语义。
容易踩的坑:有人误以为 Config::pull() 是“安全读取”,其实它带副作用;一旦在中间件或公共服务中调用了,后面控制器再想读 app 配置就会为空。
-
Config::pull('database')后,config('database.hostname')仍能读到值(因为缓存未清),但Config::get('database.hostname')就不行了 - 除非你明确需要“读一次就销毁”的语义,否则一律用
Config::get()或config() - 该方法在 TP8.0 仍存在,但文档已不推荐,实际项目中几乎见不到合理使用场景
has() 判断逻辑二者等价,但写法细节不同
判断键是否存在,Config::has('default_lang') 和 config('?default_lang') 行为一致,都是检查当前已加载配置中有没有这个 key,**不是**检查配置文件里是否定义了它。
性能影响:这个判断非常快,本质是数组 isset() 操作,无 IO、无解析开销。
-
config('?database.hostname')中的?是固定前缀,不能省略,写成config('database.hostname?')会当成普通 key 查找 -
Config::has()不支持点号嵌套语法缩写,必须写全路径:Config::has('database.hostname'),不能写Config::has('hostname')即使它在 database 子数组里 - 如果配置项本身值为
null或false,has()仍返回true,因为它只看 key 是否存在,不关心值



















