在Laravel框架中,配置系统是整个应用运行的基础。框架将数据库、缓存、邮件、应用名称等参数统一放在config目录下,通过特定的读取方式让业务代码获取这些值。理清不同读取方法的适用场景,是日常开发和维护必不可少的一环。
一、使用config助手函数读取
最常见也最推荐的方式是使用全局助手函数config()。该函数接收配置文件名和键名组成的点号路径,返回对应的配置值。例如,想要获取应用名称,只需调用config('app.name')。如果键不存在,可以传入第二个参数作为默认值。
这种方式的优势在于代码清晰、易于测试,并且始终从已加载的配置数组中取值,不受env文件是否被缓存的影响。在控制器、服务类、闭包路由中都可以随意使用。下面是一段读取多个配置项的示例:
<?php
// 读取应用名称,若不存在则返回默认
$appName = config('app.name', 'MyApp');
// 读取数据库默认连接类型
$dbConnection = config('database.default');
// 读取自定义配置文件upload.php中的max_size
$maxSize = config('upload.max_size');
var_dump($appName, $dbConnection, $maxSize);
当我们在config目录新建了upload.php文件并定义了返回数组,上述代码即可正确读取。使用config助手函数,不必担心环境配置文件被缓存之后读取不到最新手改的env值,因为它读的是配置仓库里的数据。
二、使用Config门面读取
除了助手函数,Laravel还提供了IlluminateSupportFacadesConfig门面,其底层与config()函数调用的是同一个仓库实例。在需要依赖注入或希望明确表达配置操作的地方,可以使用该门面。
门面方式支持get、set、has等方法,功能比助手函数更完整。比如你可以在运行时判断某个配置是否存在,或者临时修改配置值(仅当前请求生命周期有效)。示例如下:
<?php
use IlluminateSupportFacadesConfig;
// 判断配置是否存在
if (Config::has('cache.default')) {
$driver = Config::get('cache.default');
}
// 运行时动态修改配置
Config::set('session.lifetime', 120);
// 读取修改后的值
echo Config::get('session.lifetime');
需要注意,通过set方法修改的配置不会写回文件,仅存在于内存中。若执行了配置缓存命令,门面读取的同样是缓存内容,这能保证不同读取入口行为一致。
三、env函数与配置缓存的关系
很多初学者会直接在代码里写env('DB_HOST')来读取环境变量,这在Laravel引导阶段(如config文件自身内部)是允许的,但不建议放在业务代码中。原因在于Laravel提供了php artisan config:cache命令,它会把config下所有文件编译进一个缓存文件,此后框架不再逐行解析env文件。
一旦缓存生成,env()函数将返回null或缓存时写死的值,导致你修改.env文件后代码毫无反应。因此正确做法是:在config/database.php等配置文件中用env()读取env值并赋值给数组,业务代码统一用config()读取。下面的配置写法符合规范:
<?php
// config/database.php 片段
return [
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'mysql' => [
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
],
],
];
如果已经误执行了config:cache,又想恢复直接读env,可以运行php artisan config:clear清除缓存。生产环境通常保留缓存以提升性能,此时所有变动都应改config文件或重新缓存,而不是依赖env实时生效。
四、在服务提供者中读取与覆盖
Laravel的启动流程会先加载config文件,再启动服务提供者。如果某些配置需要根据其他配置动态决定,可以放在服务提供者的register或boot方法里用Config::set覆盖。例如根据域名切换邮件驱动:
<?php
namespace AppProviders;
use IlluminateSupportServiceProvider;
use IlluminateSupportFacadesConfig;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
if (request()->getHost() === 'admin.ipipp.com') {
Config::set('mail.driver', 'log');
}
}
}
这种做法让配置具备运行时灵活性,但要避免循环依赖,比如A配置依赖B配置而B又在后被覆盖。通常把这类逻辑放在boot中,此时基础配置已全部就绪。总体来看,Laravel读取配置值的方法虽多,核心原则就是:env只进config,业务只出config。