JFactory::getDbo() 是 Joomla 獲取資料庫連接對象的標準入口(Joomla 4/5 為 Factory::getContainer()->get(DatabaseInterface::class))。返回的 JDatabaseDriver 實例封裝了查詢構建、預處理、事務、結果集遍歷等功能。本文系統講解連接獲取、查詢構建器、各類執行方式、結果集處理、錯誤處理及最佳實踐。
use Joomla\CMS\Factory; // Joomla 3.x $db = JFactory::getDbo(); // Joomla 4/5 (推薦) $db = Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class); // 別名(向後兼容層) // $db = JFactory::getDbo();
使用 $db->getQuery(true) 獲取新的 JDatabaseQuery 實例,鏈式構建 SQL,自動處理表前綴(#__)、識別符轉義、參數綁定。
$query = $db->getQuery(true)
->select($db->qn(['id', 'title', 'alias', 'created']))
->from($db->qn('#__content'))
->where($db->qn('state') . ' = 1')
->where($db->qn('catid') . ' IN (' . implode(',', array_map('intval', $catIds)) . ')')
->order($db->qn('created') . ' DESC')
->setLimit(20, 0);
$db->setQuery($query);
// 執行並獲取關聯陣列列表
$articles = $db->loadAssocList(); // [['id'=>1,'title'=>'...'], ...]
// 或獲取對象列表
$articles = $db->loadObjectList(); // [stdClass, ...]
// 單行單值
$count = $db->loadResult(); // 第一行第一列
// 單行對象
$article = $db->loadObject();
$columns = ['title', 'alias', 'catid', 'created', 'created_by', 'state'];
$values = [
$db->q('My Article'),
$db->q('my-article'),
5,
$db->q(date('Y-m-d H:i:s')),
42,
1,
];
$query = $db->getQuery(true)
->insert($db->qn('#__content'))
->columns($db->qn($columns))
->values(implode(',', $values));
$db->setQuery($query);
$db->execute();
$newId = $db->insertid(); // 獲取自增 ID
$query = $db->getQuery(true)
->update($db->qn('#__content'))
->set([
$db->qn('title') . ' = ' . $db->q('Updated Title'),
$db->qn('modified') . ' = ' . $db->q(date('Y-m-d H:i:s')),
$db->qn('modified_by') . ' = 42',
])
->where($db->qn('id') . ' = 123');
$db->setQuery($query);
$affected = $db->execute(); // 返回影響行數
$query = $db->getQuery(true)
->delete($db->qn('#__content'))
->where($db->qn('id') . ' = 123');
$db->setQuery($query);
$affected = $db->execute();
// 準備語句
$query = $db->getQuery(true)
->select('*')
->from($db->qn('#__users'))
->where($db->qn('id') . ' = :id');
$db->setQuery($query);
// 綁定參數並執行多次
$stmt = $db->prepare($query);
$stmt->bindParam(':id', $id, \PDO::PARAM_INT);
foreach ([1, 2, 3, 4] as $id) {
$stmt->execute();
$user = $stmt->fetchObject();
// 處理 $user
}
| 方法 | 返回類型 | 適用場景 |
|---|---|---|
loadAssocList() | array[] (關聯陣列) | 列表頁、API 返回 JSON |
loadAssocList('key') | array[key => row] | 需按主鍵快速查找 |
loadObjectList() | stdClass[] | 習慣物件訪問屬性 |
loadObjectList('key') | array[key => obj] | 同關聯陣列 |
loadRowList() | array[] (數值索引) | CSV 導出、矩陣運算 |
loadColumn() | array (單列值) | 獲取 ID 列表、標籤列表 |
loadResult() | mixed (單值) | COUNT(*)、MAX(id) 等聚合 |
loadObject() | stdClass|null | 單行記錄 |
loadAssoc() | array|null | 單行關聯陣列 |
getNumRows() | int | 影響/返回行數(SELECT 需先 execute) |
try {
$db->transactionStart();
$db->setQuery($insertQuery1)->execute();
$db->setQuery($updateQuery2)->execute();
$db->setQuery($deleteQuery3)->execute();
$db->transactionCommit();
} catch (\Exception $e) {
$db->transactionRollback();
// 記錄日誌、拋出或返回錯誤
throw new \RuntimeException('Database transaction failed: ' . $e->getMessage());
}
$db->setQuery($query);
if (!$db->execute()) {
$errorNum = $db->getErrorNum();
$errorMsg = $db->getErrorMsg();
// 記錄日誌
\Joomla\CMS\Log\Log::add("DB Error [$errorNum]: $errorMsg | SQL: " . $db->getQuery(), \Joomla\CMS\Log\Log::ERROR, 'database');
return false;
}
// 調試:輸出最終 SQL(不執行)
echo $db->getQuery(); // 或 $query->__toString()
// 調試:替換參數後的完整 SQL(僅調試用,生產禁用)
echo $db->replacePrefix((string)$query);
$db->quote($value) / $db->q($value):字串轉義加引號$db->quoteName($name) / $db->qn($name):識別符轉義(反引號/雙引號/方括號)$db->escape($string):僅轉義不加引號$db->getPrefix():獲取表前綴(如 jos_)$db->getVersion():資料庫服務器版本#__ 前綴,由驅動自動替換為實際前綴。qn(),數值用 q()。setLimit() + 迴圈,避免記憶體溢出。mysql_* 遷移對照表| 舊寫法 | Joomla DBO 寫法 |
|---|---|
mysql_query($sql) | $db->setQuery($sql)->execute() |
mysql_fetch_assoc($res) | $db->loadAssoc() |
mysql_fetch_array($res) | $db->loadRow() / $db->loadAssoc() |
mysql_num_rows($res) | $db->getNumRows() |
mysql_insert_id() | $db->insertid() |
mysql_real_escape_string($v) | $db->escape($v) / $db->q($v) |
掌握 JFactory::getDbo() 獲取連接、查詢構建器鏈式構建、預處理參數綁定、多樣結果集加載、事務控制與錯誤處理,即可在 Joomla 擴展中編寫安全、高效、可維護的資料庫操作代碼。遵循「構建器優先、參數綁定、前綴自動、事務保障」原則,拒絕裸 SQL 拼接,是專業 Joomla 開發者的基本功。