配置

配置文件

Laravel 框架的所有配置文件都在 config 目录里。每个选项都附了文档注释,建议你翻一翻文件,熟悉有哪些可调项。

这些配置文件能让你配置数据库连接信息、邮件服务器信息,以及应用 URL、加密密钥等各种核心配置值。

about 命令:一览应用配置

Laravel 提供了 about Artisan 命令,跑一下就能看到一份应用配置、驱动和环境的总览:

php artisan about

如果你只关心总览里的某一节,用 --only 选项过滤:

php artisan about --only=environment

想详细看某个配置文件里的值,用 config:show 命令:

php artisan config:show database

环境配置

不同环境(本地开发 vs 生产服务器)往往需要不同的配置值,比如本地和生产用不同的缓存驱动。Laravel 用 DotEnv 这个 PHP 库来管这事。新装的 Laravel 根目录有个 .env.example 文件,列了一堆常见环境变量;安装过程中它会自动复制出 .env 文件。

Laravel 默认的 .env 里是一些可随环境变化的常见配置值,config 目录里的配置文件通过 env() 函数读取这些值。

如果你在团队里开发,建议持续维护 .env.example:在里面放占位值,队友就能看出跑你这个应用需要哪些环境变量。

外部环境变量能覆盖 .env

.env 里写的变量,可能被"外部环境变量"盖掉——外部环境变量指在 .env 文件之外、由服务器或操作系统层设的,比如 Nginx 配置里的 fastcgi_param、Docker 的 -e 参数、systemd 的 Environment=、或 shell 的 export。Laravel 用 DotEnv 把 .env 加载进 PHP,但如果某个变量名在 PHP 启动前就已经存在于操作系统环境里,DotEnv 默认不会覆盖它——env() 拿到的是外部那个值,不是 .env 里写的。所以部署时敏感值可以不写进 .env,改用服务器环境变量注入,更安全。

.env 文件安全

.env 不应该提交到源码仓库——每个开发者、每台服务器可能需要不同的环境配置;万一有人拿到你的源码仓库,里面夹带的敏感凭证就全暴露了。不过 Laravel 自带 环境加密 功能,加密后的 .env 可以安全地放进源码仓库。

常见坑:.env 不进 git

.env 里有数据库密码、API 密钥等敏感信息,别提交。要进版本控制就先用下面的 env:encrypt 加密。

额外的环境文件

加载环境变量前,Laravel 会先看有没有外部传入的 APP_ENV 环境变量或 --env CLI 参数。有就尝试加载 .env.[APP_ENV] 文件(比如 APP_ENV=staging 就加载 .env.staging);不存在就退回默认的 .env。

环境变量的类型

.env 里的变量默认都按字符串解析,但是 Laravel 预留了几个特殊值,让你能从 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 里的变量都会被加载进 $_ENV 这个 PHP 超全局数组。你可以用 env() 函数取这些值。阅读 Laravel 的配置文件时,你会发现很多选项已经在用它:

'debug' => (bool) env('APP_DEBUG', false),

传给 env() 的第二个值是"默认值"——当对应的环境变量不存在时返回它。

判断当前环境

当前应用环境由 .env 里的 APP_ENV 决定。通过 App 门面 的 environment() 方法取这个值:

术语:门面 Facade

门面(Facade)是 Laravel 给一类静态式调用的封装——你写 App::environment(),背后实际是框架从服务容器里拿出对应实例调方法。看起来像静态方法,实则是可测、可换的实例方法。

use Illuminate\Support\Facades\App;

$environment = App::environment();
// 不传值,等价于
$environment = env('APP_ENV', 'production');

也可以传参数判断当前环境是否匹配,命中任意一个就返回 true:

if (App::environment('local')) {
    // 当前是 local 环境
}

if (App::environment(['local', 'staging'])) {
    // 当前是 local 或 staging
}

信息

在服务器级定义一个 APP_ENV 环境变量,可以覆盖当前应用环境的探测结果。

加密环境文件

未加密的环境文件绝不该放进源码仓库。Laravel 允许你加密环境文件,加密后就能跟应用代码一起安全入库。

加密

用 env:encrypt 命令加密:

php artisan env:encrypt

它会加密你的 .env,把密文写进 .env.encrypted。解密密钥会打印在命令输出里,务必存到安全的密码管理器。想自己指定密钥,用 --key:

php artisan env:encrypt --key=3UVsEgGVK36XN82KKeyLFMhvosbZN1aF

信息

密钥长度要和加密算法对得上。Laravel 默认用 AES-256-CBC,需要 32 字符的密钥。可以用 --cipher 换成 Laravel 加密器 支持的其它算法。

如果有多个环境文件(如 .env 和 .env.staging),用 --env 指定加密哪个:

php artisan env:encrypt --env=staging

可读变量名

加密时加 --readable,可以保留变量名可见、只加密值:

php artisan env:encrypt --readable

产出的加密文件长这样:

APP_NAME=eyJpdiI6...
APP_ENV=eyJpdiI6...
APP_KEY=eyJpdiI6...
APP_DEBUG=eyJpdiI6...
APP_URL=eyJpdiI6...

可读格式的好处:不暴露敏感值,就能看出有哪些变量;review PR 时也能直接看出哪个变量被新增/删除/改名,不用解密。解密时 Laravel 会自动识别用了哪种格式,env:decrypt 不用额外选项。

信息

用 --readable 时,原 .env 里的注释和空行不会保留到加密输出里。

解密

用 env:decrypt 解密。它需要解密密钥,Laravel 会从 LARAVEL_ENV_ENCRYPTION_KEY 环境变量取:

php artisan env:decrypt

也可以直接用 --key 传:

php artisan env:decrypt --key=3UVsEgGVK36XN82KKeyLFMhvosbZN1aF

跑完会把 .env.encrypted 的内容解密写回 .env。用 --cipher 指定自定义算法:

php artisan env:decrypt --key=qUWuNRdfuImXcKxZ --cipher=AES-128-CBC

多个环境文件时用 --env 指定解密哪个:

php artisan env:decrypt --env=staging

要覆盖已存在的环境文件,加 --force:

php artisan env:decrypt --force

部署到服务器怎么用

典型流程:本地 env:encrypt 加密后把 .env.encrypted 提交进 git;服务器上只注入一个 LARAVEL_ENV_ENCRYPTION_KEY 环境变量(Nginx fastcgi_param / Docker -e / systemd Environment= 任选),部署脚本里跑一次 php artisan env:decrypt 生成 .env,Laravel 启动时读的就是这个解密后的 .env。注意:框架启动时不会自动解密 .env.encrypted——必须先跑 env:decrypt 把 .env 落地,否则应用拿不到配置。所以 .env.encrypted 只是"安全运输/存储"用的,运行时还是靠 .env。

访问配置值

在应用任何地方,都能用 Config 门面或全局 config() 函数访问配置值。用"点语法"——文件名.选项名——指定要取的项。也可以给默认值,选项不存在时返回它:

use Illuminate\Support\Facades\Config;

$value = Config::get('app.timezone');

$value = config('app.timezone');

// 选项不存在时返回默认值
$value = config('app.timezone', 'Asia/Seoul');

运行时改配置值,用 Config 门面的 set() 方法,或给 config() 函数传数组:

Config::set('app.timezone', 'America/Chicago');

config(['app.timezone' => 'America/Chicago']);

为了配合静态分析,Config 门面还提供了一组类型化取值方法。取到的值类型不对时会抛异常:

Config::string('config-key');
Config::integer('config-key');
Config::float('config-key');
Config::boolean('config-key');
Config::array('config-key');
Config::collection('config-key');

配置缓存

为了提速,用 config:cache 把所有配置文件合并成一个文件,框架加载起来飞快:

php artisan config:cache

这条命令通常作为生产部署流程的一步。本地开发别跑——开发时配置值经常要改,缓存了反而碍事。

配置缓存后,请求和 Artisan 命令期间框架不再加载 .env,因此 env() 函数只会返回外部的、系统级环境变量。所以务必只在 config 目录里的配置文件中调用 env() 函数——你能在 Laravel 默认配置文件里看到大量这种用法。在应用其它地方要读配置,用上面 访问配置值 说的 config() 函数。

用 config:clear 清掉缓存:

php artisan config:clear

常见坑:env() 用错地方

部署时跑了 config:cache 后,.env 就不再被加载。如果你在业务代码(而非配置文件)里调了 env('APP_KEY'),缓存生效后会拿到 null 或外部环境变量,不是 .env 里写的值——这是经典踩坑。规则:env() 只在 config/ 文件里用;其它地方一律 config()。

发布配置

Laravel 大部分配置文件已经发布到应用的 config 目录了;但像 cors.php、view.php 这类默认没有被生成出文件,因为多数应用用不着改。需要的话用 config:publish 发布(发布就是生成文件的意思):

php artisan config:publish # 在命令行中可以选择你要发布的具体配置文件

php artisan config:publish --all # 发布所有的内置配置文件

调试模式

config/app.php 里的 debug 选项决定向用户展示多少错误信息。默认它读 .env 里的 APP_DEBUG 值。

常见坑:生产环境必须关 DEBUG

本地开发把 APP_DEBUG=true。生产环境永远是 false——设成 true 会把敏感配置值暴露给终端用户。

维护模式

应用进入维护模式后,所有请求都展示一个自定义视图,方便你在更新或维护期间"关掉"应用。默认中间件栈里带维护模式检查;命中维护模式时抛 Symfony\Component\HttpKernel\Exception\HttpException,状态码 503。

开启维护模式:

php artisan down

想让浏览器定时自动刷新维护页,用 --refresh 选项——值是秒数,Laravel 会把它作为 Refresh HTTP 头发出,浏览器收到后每隔这个秒数自动重新加载页面。好处是:维护结束你跑 php artisan up 恢复后,用户的浏览器下一次自动刷新(最多等这个秒数)就能看到正常站点,不用他们自己反复点刷新猜"好了没":

php artisan down --refresh=15

--retry 选项会设成 Retry-After HTTP 头的值——Retry-After 是标准的 HTTP 头,配合 503 状态码用,告诉客户端"过 N 秒再来试这个请求"。它主要给 API 客户端和搜索引擎爬虫(如 Googlebot)看:爬虫收到 503 + Retry-After 就知道站点只是临时维护、过会儿重试,不会当成永久下线而影响 SEO。浏览器一般忽略这个头,所以给人看的页面还得靠上面的 --refresh 自动刷新。两个选项各管一摊:--refresh 给人,--retry 给机器:

php artisan down --retry=60

实际怎么选

两个不冲突,可以一起用:php artisan down --refresh=15 --retry=60——--refresh 让浏览器用户 15 秒自动刷新看到恢复,--retry 让爬虫/API 客户端 60 秒后重试、保 SEO。只挑一个的话:多数 Web 站点(给人看页面)选 --refresh;纯 API 服务(没有页面给人刷新)选 --retry。

绕过维护模式

用 --secret 指定一个绕过令牌,就能在维护模式下用这个令牌访问:

php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515"

进入维护模式后,你访问带这个令牌的应用 URL,Laravel 会给浏览器发一个绕过维护模式的 cookie:

https://yeetu.com/1630542a-246b-4b66-afa1-dd72a4c43515

想让 Laravel 自动生成令牌,用 --with-secret,应用进入维护模式后会把令牌显示给你:

php artisan down --with-secret

访问这个隐藏路由后,你会被重定向到 /。cookie 发到浏览器后,你就能像平时一样浏览应用,仿佛它不在维护模式。

信息

维护模式令牌通常用字母数字字符,可加短横线。别用 ?、& 这类在 URL 里有特殊含义的字符。

多服务器下的维护模式

默认 Laravel 用基于文件的方式判断是否在维护模式——意味着要在每台跑应用的服务器上都执行 php artisan down。Laravel 也提供基于缓存的方式:只需在一台服务器上跑 php artisan down。在 .env 里改维护模式相关变量,选一个所有服务器都能访问的缓存 store,保证各服务器状态一致:

APP_MAINTENANCE_DRIVER=cache
APP_MAINTENANCE_STORE=database

预渲染维护页

部署时跑 php artisan down,如果用户刚好在你更新 Composer 依赖或基础设施时访问,可能还是会撞上错误——因为 Laravel 得先启动一大半框架,才能判断维护模式并渲染维护页。为此 Laravel 允许你预渲染一个维护页,在请求周期最开头就返回,不依赖任何应用依赖。用 --render 指定模板:

php artisan down --render="errors::503"

维护模式重定向

维护模式下默认对所有 URL 展示维护页。如果你想全部重定向到某个 URL,用 --redirect,比如重定向到 /:

php artisan down --redirect=/

关闭维护模式

用 up 命令关闭:

php artisan up

信息

在 resources/views/errors/503.blade.php 放你自己的模板,可以自定义默认维护页。

维护模式与队列

维护模式期间,队列任务不会被处理;应用退出维护模式后恢复正常。

维护模式的替代方案

维护模式总归有几秒停机。要零停机部署,可以考虑把应用跑在 Laravel Cloud 这类全托管平台上。