配置
简介
Laravel 框架的所有配置文件都存放在 config
目录下,每个配置项都有文档,你可以整体阅读下所有这些配置文件来熟悉配置项的作用和位置。
这些配置文件允许你配置数据连接信息、邮箱服务器信息、以及很多其他核心配置信息,比如应用时区、加密密钥等。
环境配置
基于应用运行的环境不同设置不同的配置值能够给我们开发带来极大的方便,比如,我们通常在本地和线上环境配置不同的缓存驱动,这一功能在 Laravel 中很容易实现。
Laravel 使用 PHP 扩展库 DotEnv 来实现这一功能,在新安装的 Laravel 中,根目录下有一个 .env.example
文件,如果 Laravel 是通过 Composer 安装的,那么该文件已经被重命名为 .env
,否则的话你要自己手动重命名该文件。
不要试图将 .env
文件提交到版本控制系统(如 Git 或 Svn)中,一方面,开发环境和线上环境配置值不一样,提交没有意义,更重要的是,.env
包含了很多应用敏感信息,如数据库用户名及密码等,如果不慎将代码提交到 Github 公开仓库,后果将不堪设想!
如果你是在一个团队中进行开发,则需要将 .env.example
文件随你的应用代码一起提交到源码控制中:将一些配置值以占位符的方式放置在 .env.example
文件中,这样其他开发者就会很清楚运行你的应用需要配置哪些环境变量。
还可以创建一个 .env.testing
文件,该文件会在运行 PHPUnit 测试或执行带有 --env=testing
选项的 Artisan 命令时覆盖从 .env
文件读取的值。
注:
.env
文件中的所有变量都可以被外部环境变量覆盖,例如服务器级别或系统级别的环境变量。
环境文件安全
.env
文件不应该被提交到代码仓库,尤其是公开的代码仓库,因为每个开发者/服务器使用不同的环境配置,此外,这也会带来安全隐患 —— 增加被入侵者获取到这些配置信息对系统进行攻击的风险。
环境变量类型
.env
文件中所有变量都会被解析为字符串,因此创建了一些保留值以便从 env()
函数返回更广泛的类型:
.env 值 |
env() 值 |
---|---|
true | (bool)true |
(true) | (bool)true |
false | (bool)false |
(false) | (bool)false |
empty | (string)'' |
(empty) | (string)'' |
null | (null)null |
(null) | (null)null |
如果你需要定义一个包含空格的环境变量值,可以通过将字符串放到双引号中来实现:
APP_NAME="My Application"
获取环境变量配置值
应用每次接受请求时,.env
中列出的所有配置及其对应值都会被载入到 PHP 超全局变量 $_ENV
中,然后你就可以在应用中通过辅助函数 env()
来获取这些配置值。实际上,如果你去查看 Laravel 的配置文件,就会发现很多地方已经在使用这个辅助函数了:
'debug' => env('APP_DEBUG', false),
传递到 env()
函数的第二个参数是默认值,如果环境变量没有被配置将会使用该默认值。
判断当前应用环境
当前应用环境由 .env
文件中的 APP_ENV
变量决定,你可以通过 App
门面上的 environment()
方法来访问其值:
use Illuminate\Support\Facades\App;
$environment = App::environment();
你也可以向 environment()
方法传递参数来判断当前环境是否匹配给定值,如果需要的话你甚至可以传递多个值。如果当前环境与给定值匹配,该方法返回 true
:
if (App::environment('local')) {
// The environment is local
}
if (App::environment('local', 'staging')) {
// The environment is either local OR staging...
}
注:当前应用环境判断可以被服务器级别环境变量
APP_ENV
覆盖。当你需要在不同环境配置间共享同一应用时很有用,你可以在服务器配置中设置一个给定主机来匹配给定环境。
访问配置值
你可以使用全局辅助函数 config()
在应用代码的任意位置访问配置值,配置值通过「配置文件名+“.”+配置项」的方式进行访问,当配置项没有被配置的时候返回默认值:
// app 是配置文件名,timezone 是配置项,配置项有多个层级(数组)的话,使用 . 进行分隔
$value = config('app.timezone');
// 如果 app.timezone 配置值为空,则返回默认值 Asia/Shanghai
$value = config('app.timezone', 'Asia/Shanghai');
如果要在运行时设置配置值,传递数组参数到 config
方法即可:
config(['app.timezone' => 'Asia/Shanghai']);
缓存配置文件
为了给应用加速,你可以使用 Artisan 命令 config:cache
将所有配置文件的配置缓存到单个文件里,这将会将所有配置选项合并到单个文件从而被框架快速加载。
应用每次上线,都要运行一次 php artisan config:cache
,但是在本地开发时,没必要经常运行该命令,因为配置值经常会改变。
注:如果在部署过程中执行
config:cache
命令,需要确保只在配置文件中调用了env
方法。一旦配置文件被缓存后,.env
文件将不能被加载,所有对env
函数的调用都会返回null
。
调试模式
config/app.php
配置文件中的 debug
选项用于决定展示给用户的错误信息中是否包含调试信息,默认情况下,这个配置项基于 .env
文件的 APP_DEBUG
环境变量进行配置。
对于本地开发环境,需要将 APP_DEBUG
环境变量设置为 true
,而在生产环境,这个值必须被设置为 false
,如果在生产环境将其设置为 true
,则会将系统文件路径、配置值等敏感信息暴露给终端用户,进而可能被入侵者利用对系统进行攻击。
维护模式
当你的应用处于维护模式时,所有对应用的请求都应该返回同一个自定义视图。这一功能在对应用进行升级或者维护时,使得“关闭”站点变得轻而易举。对维护模式的判断代码位于应用默认的中间件栈中,如果应用处于维护模式,访问应用时状态码为 503
的 MaintenanceModeException
将会被抛出。
要开启维护模式,关闭站点,只需执行 Artisan 命令 down
即可:
php artisan down
还可以提供 retry
选项给 down
命令。retry
的值用于设置 HTTP 请求头的 Retry-After
:
php artisan down --retry=60
绕过维护模式
你可以使用 secret
选项指定绕过维护模式的令牌:
php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515"
通过这种方式启动维护模式后,可以使用带有上述令牌的 URL 访问应用(假设对应项目的域名是 example.com
):
https://example.com/1630542a-246b-4b66-afa1-dd72a4c43515
这样一来,当请求到达服务端之后,Laravel 会颁发一个用于标识绕过维护模式的 Cookie 到浏览器,然后用户会被重定向到 /
路由,由于此时用户所有请求都会自动带上浏览器中的绕过维护模式 Cookie,所以当前用户可以正常访问处于维护模式的应用,就像它并未进入维护模式一样。
预渲染维护模式视图
如果你在开发期间使用 php artisan down
命令进入维护模式,用户仍然可能偶尔遇到错误 —— 如果访问应用的同时 Composer 依赖或者其他基础设施组件正在更新。这种情况会发生是因为 Laravel 框架的基础组成部分必须启动后才能判断应用是否处于维护模式,然后使用模板引擎渲染维护模式视图。
为此,Laravel 现在允许你预渲染维护模式视图,它会在请求生命周期的早期返回,这样一来,该视图就会在所有应用依赖加载前被渲染。你可以使用 down
命令的 render
选项选择要预渲染的视图模板:
php artisan down --render="errors::503"
重定向维护模式请求
在维护模式中,Laravel 会为所有用户试图访问的 URL 返回维护模式视图,如果你需要的话,还可以告知 Laravel 将所有这些请求重定向到指定 URL。这可以通过在 down
命令中使用 redirect
选项来实现,例如,你可以将所有请求重定向到首页 URI /
:
php artisan down --redirect=/
关闭维护模式
要关闭维护模式,开启站点,对应的 Artisan 命令是 up
:
php artisan up
注:你可以通过定义自己的模板来定制默认的维护模式模板,自定义模板视图位于
resources/views/errors/503.blade.php
。
维护模式 & 队列
当你的站点处于维护模式中时,所有的队列任务都不会执行;当应用退出维护模式这些任务才会被继续正常处理。
维护模式的替代方案
由于维护模式命令的执行需要几秒时间,你可以考虑使用 Envoyer 实现零秒下线作为替代方案。
1 Comment
app.php下'timezone' => 'Asia/Shanghai',已经修改,返回的时间格式为什么不生效,还是返回:2021-06-17T09:15:35.000000Z