ThinkPHP 支援靈活的資料庫配置方式。本文介紹三種常用配置技巧:獨立配置檔複用、控制器動態連線、多資料庫切換。
`Conf/db.php`(與入口檔同級):
<?php
return array(
'DB_TYPE' => 'mysqli',
'DB_HOST' => 'localhost',
'DB_NAME' => 'demo',
'DB_USER' => 'root',
'DB_PWD' => 'root',
'DB_PREFIX' => 'think_',
'DB_CHARSET'=> 'utf8',
'DB_PARAMS' => array(
\PDO::ATTR_PERSISTENT => true, // 持久連線
),
);
`Conf/config.php`:
<?php
$appConfig = array(
'URL_MODEL' => 2,
'APP_DEBUG' => true,
'LOG_RECORD' => true,
// ... 其他應用配置
);
$dbConfig = include 'db.php'; // 引入獨立配置
return array_merge($appConfig, $dbConfig);
後台入口 `Admin/Conf/config.php` 同樣引入:
$dbConfig = include '../../Conf/db.php'; // 相對路徑指向同一檔案
return array_merge($adminConfig, $dbConfig);
優點:修改一處 `db.php`,前後台同步生效,避免配置不一致。
臨時連接不同資料庫(如跨庫查詢、同步數據):
class DataAction extends Action
{
public function sync()
{
$config = array(
'dbms' => 'mysqli', // 驅動類型
'username' => 'remote_user',
'password' => 'remote_pass',
'hostname' => '192.168.1.100',
'database' => 'remote_db',
'hostport' => '3306',
'dsn' => '', // 可選完整 DSN
);
// 實例化 Db 類(非 Model)
$db = new Db($config);
// 直接查詢
$list = $db->table('remote_table')->where('status=1')->select();
// 或執行原生 SQL
$db->execute("INSERT INTO local_table SELECT * FROM remote_table WHERE ...");
}
}
不同 Model 對應不同資料庫:
`Conf/db.php`:
return array(
'DB_CONFIG' => array(
'main' => array(
'DB_TYPE' => 'mysqli',
'DB_HOST' => 'localhost',
'DB_NAME' => 'main_db',
'DB_USER' => 'root',
'DB_PWD' => 'pass',
),
'logs' => array(
'DB_TYPE' => 'mysqli',
'DB_HOST' => '192.168.1.10',
'DB_NAME' => 'logs_db',
'DB_USER' => 'log_user',
'DB_PWD' => 'log_pass',
),
'archive' => array(
'DB_TYPE' => 'mysqli',
'DB_HOST' => '192.168.1.20',
'DB_NAME' => 'archive_db',
'DB_USER' => 'arc_user',
'DB_PWD' => 'arc_pass',
),
),
);
class BaseModel extends Model
{
protected $dbConfigKey = 'main'; // 預設資料庫
public function __construct($data = '', $tableName = '', $dbConfig = '')
{
if ($dbConfig) {
$this->dbConfigKey = $dbConfig;
}
parent::__construct($data, $tableName);
}
protected function _connect()
{
if ($this->_db) return $this->_db;
$config = C('DB_CONFIG.' . $this->dbConfigKey);
if (!$config) {
E("Database config '{$this->dbConfigKey}' not found");
}
$this->_db = Db::getInstance($config);
return $this->_db;
}
}
class UserModel extends BaseModel
{
protected $dbConfigKey = 'main';
protected $tableName = 'user';
}
class LogModel extends BaseModel
{
protected $dbConfigKey = 'logs';
protected $tableName = 'access_log';
}
class ArchiveModel extends BaseModel
{
protected $dbConfigKey = 'archive';
protected $tableName = 'old_data';
}
// 自動使用 main 資料庫
$user = M('User')->find(1);
// 自動使用 logs 資料庫
$logs = M('Log')->where('date > "2024-01-01"')->select();
// 臨時覆蓋
$temp = M('User', 'user', 'logs')->find(1); // 第三參數指定 dbConfigKey
利用 `ThinkPHP/Conf/convention.php` 慣例配置 + 專案配置覆蓋機制:
// 專案根目錄建立環境檢測
define('APP_ENV', getenv('APP_ENV') ?: 'development');
// Conf/config.php
$envConfigs = array(
'development' => array(
'DB_HOST' => 'localhost',
'DB_NAME' => 'dev_db',
'APP_DEBUG' => true,
),
'testing' => array(
'DB_HOST' => '192.168.1.10',
'DB_NAME' => 'test_db',
'APP_DEBUG' => true,
),
'production' => array(
'DB_HOST' => 'db.master.internal',
'DB_NAME' => 'prod_db',
'APP_DEBUG' => false,
'DB_PARAMS' => array(\PDO::ATTR_PERSISTENT => true),
),
);
return array_merge($commonConfig, $envConfigs[APP_ENV]);
部署時設定環境變數:
# Nginx + PHP-FPM
fastcgi_param APP_ENV production;
# Apache
SetEnv APP_ENV production
# Docker
ENV APP_ENV=production
| 場景 | 推薦方案 | 關鍵點 |
|---|---|---|
| 單資料庫、前後台共享 | 獨立 db.php + array_merge | 一處修改、多處生效 |
| 臨時跨庫查詢 | 控制器 new Db($config) | 獨立連線、不影響主連線 |
| 多業務模組分庫 | BaseModel + dbConfigKey | Model 級自動切換、透明使用 |
| 多環境部署 | 環境變數 + 陣列合併 | 配置與代碼分離、安全無硬編碼 |
| 讀寫分離 | Db 類擴展或中間件 | 主庫寫、從庫讀、自動路由 |
合理規劃資料庫配置策略,能大幅降低維護成本,避免配置漂移導致的生產事故。