ThinkPHP 的 C() 方法是框架核心配置管理的統一介面,負責配置的「讀、寫、合併、快取」。本文從原始碼層面剖析其運作機制,並示範實戰常見用法與進階擴充技巧。
| 呼叫方式 | 用途 | 回傳值 |
|---|---|---|
C('KEY') | 讀取一維配置 | 值或 null |
C('GROUP.KEY') | 讀取二維配置 | 值或 null |
C('KEY', 'value') | 設定一維配置 | null |
C('GROUP.KEY', 'value') | 設定二維配置 | null |
C(['KEY'=>'val']) | 批次設定一維 | null |
C(['K1'=>'v1'], 'GROUP') | 批次設定二維(群組) | null |
C() | 取得所有配置(除錯用) | 完整配置陣列 |
原始碼採用 static $_config = [] 靜態變數保存配置,所有鍵名統一轉為小寫:
$_config['db_password']$_config['db']['password'](群組名小寫,子鍵保持原大小寫)設計考量:團隊協作時開發者命名習慣不一(DB_PASSWORD/db_password/Db_Password),統一轉小寫避免重複佔用記憶體並確保讀取一致性。
<?php
function C($name = null, $value = null) {
static $_config = [];
// 1. 讀取/寫入單一鍵(字串模式)
if (!is_null($name)) {
if (is_string($name)) {
// --- 讀取 ---
if (is_null($value)) {
if (strpos($name, '.') === false) {
// 一維:KEY
$name = strtolower($name);
return isset($_config[$name]) ? $_config[$name] : null;
} else {
// 二維:GROUP.KEY
$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;
}
}
// 2. 批次合併/群組寫入(陣列模式)
elseif (is_array($name)) {
if (is_null($value)) {
// 合併到根層級
$_config = array_merge($_config, $name);
} else {
// 寫入指定群組(二維)
$_config[$value] = $name;
}
return;
}
}
// 3. 取得所有配置
else {
return empty($_config) ? null : $_config;
}
}
?>
<?php
// config.php
return [
'DB_TYPE' => 'mysql',
'DB_HOST' => '127.0.0.1',
'DB_NAME' => 'myapp',
'DB_USER' => 'root',
'DB_PWD' => 'secret',
'APP_DEBUG' => true,
];
// 入口檔案或初始化處
C(include 'config.php'); // 一次性載入所有配置
// 之後任意處讀取
$dbHost = C('DB_HOST'); // '127.0.0.1'
$debug = C('APP_DEBUG'); // true
?>
<?php
// 執行前:$_config = []
C(['name' => 'mysql', 'password' => 'root'], 'db');
// 執行後:$_config = ['db' => ['name' => 'mysql', 'password' => 'root']]
// 讀取
echo C('db.name'); // mysql
echo C('db.password'); // root
?>
<?php
// 根據子域名切換資料庫
$tenant = get_current_tenant();
C('DB_NAME', "app_{$tenant}");
C('DB_USER', "user_{$tenant}");
// 後續模型自動讀取新配置
?>
db, cache, upload, api),避免根層級鍵名衝突。ENV 常數載入不同環境設定檔(config_prod.php, config_dev.php)。C() 完整配置快取至檔案/Redis,避免每請求 include 解析陣列。dump(C()) 即可檢視所有生效配置。C() 方法雖然簡單,卻是 ThinkPHP 配置系統的基石。理解其「靜態快取 + 鍵名正規化 + 多維支援」的設計,能幫助開發者靈活管理專案配置,並避免常見的「大小寫不一致導致讀不到值」坑點。建議將本文範例收藏,作為開發時的快速參考。