配置文件
Viswoole 的应用配置集中存放在项目根目录的 config/ 目录下,由 Viswoole\Core\Config 统一加载与解析。本篇是配置文件格式、读取 API 与懒加载机制的完整参考。
目录结构
config/
├── app.php # 应用配置:调试、时区、服务提供者、命令
├── server.php # Swoole 服务定义
├── router.php # 路由全局配置(含路由缓存、API 文档)
├── database.php # 数据库通道配置
├── cache.php # 缓存存储配置
├── log.php # 日志通道配置
├── task.php # 异步任务配置
├── listens.php # 事件监听注册入口
├── lazy/ # 懒加载配置目录(AppInitialized 后加载)
│ └── middleware.php # 全局中间件注册
└── route/
└── route.php # 编程式路由定义(非配置,由路由器加载)只加载项目 config 目录
框架仅从项目根目录的 config/ 加载配置。依赖包内提供的默认配置需通过 php viswoole vendor:publish 发布到项目后修改,直接修改依赖包内的配置文件会在更新时丢失。
支持的文件格式
config/ 下的所有文件按扩展名分发到对应解析器,文件名(不含扩展名)作为该文件配置的一级键:
| 扩展名 | 解析方式 | 说明 |
|---|---|---|
php | include执行并取返回值 | 推荐,支持表达式与条件逻辑 |
yml / yaml | yaml_parse_file() | 需要安装 yaml 扩展;未安装时该文件被静默跳过(解析为空) |
ini | parse_ini_file()(typed 扫描器) | true/false/数字 自动转对应类型 |
json | json_decode() | 解析失败会抛出 RuntimeException,错误信息含文件路径 |
| 其他扩展名 | 忽略 | 不解析 |
PHP 格式(推荐)
<?php
declare(strict_types=1);
return [
// 支持表达式与条件逻辑
'debug' => env('app_debug', true),
'services' => env('APP_ENV') === 'local'
? [\App\Provider\DevProvider::class]
: [],
];JSON 格式
{
"menu": {
"home": "/",
"about": "/about"
}
}YAML 格式
database:
host: localhost
port: 3306INI 格式
; 支持分节,节名成为一级数组键
[features]
registration = true
rate_limiting = false读取配置
config() 助手函数
// 文件名即一级键
$debug = config('app.debug'); // 对应 config/app.php
// 点号(.)分隔的多级访问
$port = config('server.servers.http.construct.port'); // 9501
// 带默认值:键不存在(或值为 null)时返回默认值
$timeout = config('database.channels.default.options.timeout', 5);
// 只传文件名返回整个文件的配置数组
$appConfig = config('app');
// 不传参数返回全部配置
$all = config();config() 只读
config() 是纯读取助手,没有写入能力;运行期写入请使用 Config 门面的 set() 方法。
Config 门面
use Viswoole\Core\Facade\Config;
// 读取(等价 config())
Config::get('app.debug');
Config::get('app.not_exists', 'default_value');
// 检测存在性(值为 null 视为不存在)
Config::has('app.debug'); // true
Config::has('app.not_exists'); // false
// 写入:单条
Config::set('app.debug', false);
// 写入:批量(键名支持点号多级)
Config::set([
'app.debug' => false,
'app.default_timezone' => 'UTC',
]);关于 set() 的进程内语义
Config::set() 只修改当前进程内存中的配置池,不写入任何文件:
- 进程重启后恢复为文件中的值;
- 写入时自动创建缺失的中间层级(点号路径上的键不存在时创建为空数组再深入);
- 配置键区分大小写(框架以大小写敏感模式加载),写入与读取的键名大小写必须一致。
Swoole 多进程环境
配置在 Master 进程启动时加载,各 Worker 进程继承的是启动那一刻的快照。Config::set() 只影响执行它的当前进程,不会同步到其他 Worker——运行期动态调整全局配置需借助 AppInitialized 事件或 Swoole 事件在启动阶段完成,而非请求期随意修改。
同名文件合并
同一目录下允许同名但不同扩展名的配置文件(如 app.php 与 app.json),框架按文件名顺序逐个解析后数组合并,后解析者覆盖先解析者的同名键:
// config/app.php
return ['name' => 'App', 'debug' => true];
// config/app.json
{"name": "Override", "version": "1.0"}合并结果:['name' => 'App', 'debug' => true, 'version' => '1.0'](app.json 先于 app.php 解析)。
建议避免同名多格式
合并顺序依赖文件名排序,行为较为隐式。除刻意分层覆盖外,建议一个配置文件只用一种格式。
核心配置文件速览
各配置文件的完整键位说明见对应功能章节,此处仅作索引:
| 文件 | 一级键 | 关键配置 | 详见 |
|---|---|---|---|
app.php | app | debug、default_timezone、services[]、commands[] | 项目结构 |
server.php | server | default_start_server、servers.*、全局 options/events | 生产环境配置 |
router.php | router | case_sensitive、route_config_files[]、cache、api_doc | 路由配置 |
database.php | database | default、debug、channels.* | 数据库配置 |
cache.php | cache | default、stores.* | 缓存 |
log.php | log | default、type_channel、channels.* | 日志配置 |
task.php | task | store、expire、topics | 异步任务 |
listens.php | — | 直接调用 Event::on() 注册监听 | 事件系统 |
懒加载机制
工作原理
config/lazy/ 子目录中的配置不会在进程启动时立即加载。Config 在构造时加载主目录后,会监听 AppInitialized 事件,待应用初始化完成后再加载 lazy/ 目录:
进程启动
├─ 加载 config/*.php ← 立即加载
├─ 注册服务提供者、绑定核心组件
├─ 触发 AppInitialized 事件
│ └─ Config 加载 config/lazy/*.php ← 此刻才加载
└─ 服务就绪,开始处理请求这样做的收益:启动阶段跳过非关键配置的解析与执行,减少启动时间与内存占用。
内置的懒加载文件
框架默认在 config/lazy/middleware.php 中注册全局中间件:
<?php
declare(strict_types=1);
use Viswoole\Core\Facade\Middleware;
use Viswoole\Core\Middlewares\AllowCrossDomain;
// 该中间件用于解决跨域请求问题
Middleware::register(AllowCrossDomain::class);它不是"返回数组"的配置
lazy/middleware.php 是一段被执行的注册代码而非返回数组的配置文件——由于加载发生在 AppInitialized 之后,此时中间件门面已可用,可以安全注册。因此它无法通过 config('middleware.xxx') 访问。
自定义懒加载配置
普通的懒加载配置文件返回数组,访问方式与主目录配置完全一致:
<?php
// config/lazy/permissions.php —— 权限矩阵数据量大,延迟加载
declare(strict_types=1);
return [
'permissions' => [
'user.create' => '创建用户',
'user.read' => '查看用户',
],
'roles' => [
'admin' => ['*'],
'viewer' => ['user.read'],
],
];// 请求处理阶段访问,安全
$permissions = config('permissions.permissions');适合与不适合放入 lazy/
| 适合懒加载 | 不适合懒加载 |
|---|---|
| 路由解析后才用到的配置(如中间件) | 启动必需的核心配置(app、server、cache、log、database 等) |
| 数据量大的业务配置(权限矩阵、菜单树) | 启动阶段(服务提供者 register())就要读取的配置 |
| 特定功能才用到的第三方 SDK 配置 | 被立即加载配置引用的配置 |
时序红线
AppInitialized 之前访问懒加载配置会得到 null:
use Viswoole\Core\Service\Provider;
// ❌ 错误:Provider 的 register() 在 AppInitialized 之前执行
// 此时 config/lazy/permissions.php 尚未加载
class AppProvider extends Provider
{
public function register(): void
{
config('permissions.permissions'); // null!
}
}
// ✅ 正确:请求处理阶段访问,此时懒加载已完成
class PermissionService
{
public function can(string $permission): bool
{
return in_array($permission, config('permissions.permissions', []), true);
}
}同理,主目录配置文件中也不要引用懒加载配置——依赖链应保持在同一加载批次(要么都立即加载,要么都懒加载)。
