在 ThinkPHP 3.x 時代,C() 是框架核心配置管理的入口。它以極簡的 API 實現了配置的「寫入、讀取、合併、多維存取」等功能。本文將從原理、用法、原始碼實現三個維度深度剖析,助你徹底掌握這個「小而美」的工具函數。
| 操作類型 | 語法範例 | 說明 |
|---|---|---|
| 設定一維陣列 | C('USER_NAME', '小陳'); | 單一鍵值對 |
| 批次設定一維 | C(['USER_NAME'=>'chen', 'USER_HEIGHT'=>'170']); | 合併到 $_config |
| 設定二維陣列 | C(['DB_PASSWORD'=>'root'], 'DB'); | 指定命名空間 DB |
| 點號語法設定 | C('DB.USER_NAME', 'XIAOCHEN'); | 自動建立二維結構 |
| 讀取一維 | C('USER_NAME'); | 回傳值或 null |
| 讀取二維 | C('DB.DB_PASSWORD'); | 點號分隔命名空間 |
| 除錯檢視全部 | C(); | 回傳完整 $_config 陣列 |
團隊協作時,有人習慣 DB_PASSWORD、有人用 db_password、甚至 Db_Password。為避免佔用多份記憶體且查找失效,C() 內部統一將第一層鍵名轉為小寫:
// 內部處理邏輯
$name = strtolower($name); // 一維
// 或
$name[0] = strtolower($name[0]); // 二維第一層
因此 C('DB_PASSWORD')、C('db_password')、C('Db_Password') 實際存取同一個位置。
function C($name = null, $value = null) {
static $_config = []; // 靜態變數,生命週期貫穿整個請求
if (!is_null($name)) {
// ---------- 字串模式:讀取或單一寫入 ----------
if (is_string($name)) {
if (is_null($value)) { // 讀取
if (strpos($name, '.') === false) {
$name = strtolower($name);
return isset($_config[$name]) ? $_config[$name] : null;
} else { // 二維讀取 DB.DB_PASSWORD
$name = explode('.', $name);
$name[0] = strtolower($name[0]);
return isset($_config[$name[0]][$name[1]]) ? $_config[$name[0]][$name[1]] : null;
}
} else { // 寫入
if (strpos($name, '.') === false) {
$_config[strtolower($name)] = $value;
} else {
$name = explode('.', $name);
$_config[strtolower($name[0])][$name[1]] = $value;
}
return;
}
}
// ---------- 陣列模式:批次合併或指定命名空間 ----------
if (is_array($name)) {
if (is_null($value)) {
$_config = array_merge($_config, $name); // 一維合併
} else {
$_config[$value] = $name; // 二維:$value 為命名空間
}
return;
}
}
// ---------- 無參數:回傳全部配置 ----------
return empty($_config) ? null : $_config;
}
// config.php 回傳陣列
return [
'DB_TYPE' => 'mysql',
'DB_HOST' => '127.0.0.1',
'DB_NAME' => 'my_db',
'DB_USER' => 'root',
'DB_PWD' => 'secret',
'APP_DEBUG' => true,
];
// 入口檔或 Common 函數庫
C(include 'config.php'); // 一次性載入所有設定
// 針對 API 模組關閉除錯
if (MODULE_NAME === 'Api') {
C('APP_DEBUG', false);
}
// 原版僅支援二維,擴充後可支援 C('a.b.c', 'val')
// 實作時需遞迴建立 $_config['a']['b']['c'] = 'val'
array_merge 後載入的會覆蓋先載入的同名鍵,利用此特性可實現「預設值 → 環境覆蓋 → 區域覆蓋」的分層配置。C() 用不到 50 行程式碼,卻解決了配置管理的核心痛點:統一入口、多維存取、大小寫無感、批次合併。理解其原理,不僅能在 ThinkPHP 專案中得心應手,更能啟發你設計自己的輕量配置管理器。