Laravel 启动时自动加载 config/ 目录下所有合法 PHP 文件(小写+下划线命名、末尾 return 数组),文件名作为配置键前缀;修改后需 config:clear(开发)或 config:cache(生产)生效,且配置文件中不可调用容器或 Facade。

config 文件夹里的 PHP 文件怎么被 Laravel 读到
Laravel 启动时会自动加载 config/ 目录下所有 PHP 文件,每个文件必须返回一个数组,这个数组就是配置项。不是所有 PHP 文件都行——文件名(不含 .php)会变成配置键名,比如 app.php 对应 config('app.name')。
常见错误现象:config('myconfig.key') 返回 null,但文件明明存在。原因通常是:
- 文件没放在
config/目录下(比如放错到app/或resources/) - 文件名含大写字母或特殊符号(Laravel 只认小写+下划线,如
my_config.php合法,MyConfig.php不合法) - 文件末尾没 return 数组,或 return 前有 echo/print 语句(导致 parse error 或返回值被污染)
自定义配置文件如何生效(不重启服务)
开发中改了 config/myapp.php,但 config('myapp.timeout') 还是旧值——这是 Laravel 的配置缓存机制在起作用。本地开发时,Laravel 默认不缓存配置;但一旦运行过 php artisan config:cache,所有配置就固化成一个静态数组,不再读取原始 PHP 文件。
所以真实场景下要分两种情况处理:
- 本地开发:确保没执行过
config:cache;如果执行过,用php artisan config:clear清掉缓存即可 - 线上环境:改完配置后必须重新运行
php artisan config:cache,否则新配置永远不会加载 - CI/CD 部署脚本里漏掉
config:cache是高频翻车点,尤其当配置里有环境变量(如env('DB_HOST'))时,缓存后 env 调用会被提前求值,导致不同环境拿到同一份“编译后”的配置
config() 函数读取嵌套值的写法和边界
config() 支持用点号访问多层嵌套,比如 config('database.connections.mysql.host'),但它不支持动态拼接键名(如 config('database.connections.' . $driver . '.host') 在某些 PHP 版本可能触发 notice)。
更关键的是默认值逻辑:第二个参数是 fallback,但只在「键完全不存在」时生效,不是「值为 null/false/empty」时都触发。例如:
return [
'timeout' => null,
];
此时 config('myapp.timeout', 30) 仍返回 null,不会 fallback 到 30。
安全做法是显式判断:
$timeout = config('myapp.timeout');
if ($timeout === null) {
$timeout = 30;
}
或者用空合并操作符(PHP 7.0+):$timeout = config('myapp.timeout') ?? 30;
为什么 config 文件里不能直接 new 类或调用 service container
因为配置文件在 Laravel 容器初始化之前就被载入了。所有 app()、resolve()、依赖注入相关功能都不可用。试图在 config/app.php 里写 app()->make(MyService::class) 会导致 Call to a member function make() on null。
典型误用场景:
- 想在配置里动态生成密钥,写
Str::random(32)——Str是 facade,底层依赖容器,此时未就绪 - 把数据库连接参数写成
env('DB_HOST') ?: config('fallback.db_host')—— 看似合理,但config()在当前文件里调用自己会引发无限递归 - 用
__DIR__拼路径时没注意 config 文件本身就在config/下,结果路径多了一层
真正需要运行时逻辑的地方,应该放到 service provider 的 boot() 或 register() 方法里,而不是塞进配置文件。


















