XoopsDatabase 類別
XoopsDatabase 類別為 XOOPS 提供資料庫抽象層,處理連線管理、查詢執行、結果處理和錯誤處理。它透過驅動程式架構支援多個資料庫驅動程式。
namespace Xoops\Database;
abstract class XoopsDatabase{ protected $conn; protected $prefix; protected $logger;
abstract public function connect(bool $selectdb = true): bool; abstract public function query(string $sql, int $limit = 0, int $start = 0); abstract public function fetchArray($result): ?array; abstract public function fetchObject($result): ?object; abstract public function getRowsNum($result): int; abstract public function getAffectedRows(): int; abstract public function getInsertId(): int; abstract public function escape(string $string): string;}XoopsDatabase (Abstract Base)├── XoopsMySQLDatabase (MySQL Extension)│ └── XoopsMySQLDatabaseProxy (Security Proxy)└── XoopsMySQLiDatabase (MySQLi Extension) └── XoopsMySQLiDatabaseProxy (Security Proxy)
XoopsDatabaseFactory└── Creates appropriate driver instances取得資料庫實例
Section titled “取得資料庫實例”// Recommended: Use the factory$db = XoopsDatabaseFactory::getDatabaseConnection();使用 getInstance
Section titled “使用 getInstance”// Alternative: Direct singleton access$db = XoopsDatabase::getInstance();// Legacy: Use global variableglobal $xoopsDB;connect
Section titled “connect”建立資料庫連線。
abstract public function connect(bool $selectdb = true): bool參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$selectdb | bool | 是否選擇資料庫 |
傳回值: bool - 成功連線時為 true
範例:
$db = XoopsDatabaseFactory::getDatabaseConnection();if ($db->connect()) { echo "Connected successfully";}執行 SQL 查詢。
abstract public function query( string $sql, int $limit = 0, int $start = 0): mixed參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$sql | string | SQL 查詢字串 |
$limit | int | 返回的最大列數(0 = 無限制) |
$start | int | 起始偏移 |
傳回值: resource|bool - 結果資源或失敗時為 false
範例:
$db = XoopsDatabaseFactory::getDatabaseConnection();
// Simple query$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE uid > 0";$result = $db->query($sql);
// Query with limit$sql = "SELECT * FROM " . $db->prefix('users');$result = $db->query($sql, 10, 0); // First 10 rows
// Query with offset$result = $db->query($sql, 10, 20); // 10 rows starting at row 20queryF
Section titled “queryF”執行強制查詢(繞過安全檢查)。
public function queryF(string $sql, int $limit = 0, int $start = 0): mixed用途:
- INSERT、UPDATE、DELETE 操作
- 當您需要繞過唯讀限制時
範例:
$sql = sprintf( "UPDATE %s SET views = views + 1 WHERE article_id = %d", $db->prefix('articles'), $articleId);$db->queryF($sql);prefix
Section titled “prefix”預先設定資料庫表格前綴。
public function prefix(string $table = ''): string參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$table | string | 不含前綴的表格名稱 |
傳回值: string - 含前綴的表格名稱
範例:
$db = XoopsDatabaseFactory::getDatabaseConnection();
echo $db->prefix('users'); // "xoops_users" (if prefix is "xoops_")echo $db->prefix('modules'); // "xoops_modules"echo $db->prefix(); // "xoops_" (just the prefix)fetchArray
Section titled “fetchArray”將結果列提取為關聯陣列。
abstract public function fetchArray($result): ?array參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$result | resource | 查詢結果資源 |
傳回值: array|null - 關聯陣列或如果沒有更多列則為 null
範例:
$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE level > 0";$result = $db->query($sql);
while ($row = $db->fetchArray($result)) { echo "User: " . $row['uname'] . "\n"; echo "Email: " . $row['email'] . "\n";}fetchObject
Section titled “fetchObject”將結果列提取為物件。
abstract public function fetchObject($result): ?object參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$result | resource | 查詢結果資源 |
傳回值: object|null - 具有各欄位屬性的物件
範例:
$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE uid = 1";$result = $db->query($sql);
if ($user = $db->fetchObject($result)) { echo "Username: " . $user->uname; echo "Email: " . $user->email;}fetchRow
Section titled “fetchRow”將結果列提取為數值陣列。
abstract public function fetchRow($result): ?array範例:
$sql = "SELECT uname, email FROM " . $db->prefix('users');$result = $db->query($sql);
while ($row = $db->fetchRow($result)) { echo "Username: " . $row[0] . ", Email: " . $row[1];}fetchBoth
Section titled “fetchBoth”將結果列提取為關聯陣列和數值陣列。
abstract public function fetchBoth($result): ?array範例:
$result = $db->query($sql);$row = $db->fetchBoth($result);echo $row['uname']; // By nameecho $row[0]; // By indexgetRowsNum
Section titled “getRowsNum”取得結果集中的列數。
abstract public function getRowsNum($result): int參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$result | resource | 查詢結果資源 |
傳回值: int - 列數
範例:
$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE level > 0";$result = $db->query($sql);$count = $db->getRowsNum($result);echo "Found $count active users";getAffectedRows
Section titled “getAffectedRows”取得上次查詢受影響的列數。
abstract public function getAffectedRows(): int傳回值: int - 受影響的列數
範例:
$sql = "UPDATE " . $db->prefix('users') . " SET last_login = " . time() . " WHERE uid = 1";$db->queryF($sql);$affected = $db->getAffectedRows();echo "Updated $affected rows";getInsertId
Section titled “getInsertId”取得上次 INSERT 自動產生的 ID。
abstract public function getInsertId(): int傳回值: int - 上次插入 ID
範例:
$sql = sprintf( "INSERT INTO %s (title, content) VALUES (%s, %s)", $db->prefix('articles'), $db->quoteString($title), $db->quoteString($content));$db->queryF($sql);$newId = $db->getInsertId();echo "Created article with ID: $newId";escape
Section titled “escape”逃脫字串以安全地在 SQL 查詢中使用。
abstract public function escape(string $string): string參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$string | string | 要逃脫的字串 |
傳回值: string - 逃脫的字串(不含引號)
範例:
$unsafeInput = "O'Reilly";$safe = $db->escape($unsafeInput); // "O\'Reilly"
$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE uname = '" . $safe . "'";quoteString
Section titled “quoteString”逃脫和引用字串以用於 SQL。
public function quoteString(string $string): string參數:
| 參數 | 型別 | 描述 |
|---|---|---|
$string | string | 要引用的字串 |
傳回值: string - 逃脫和引用的字串
範例:
$name = "John O'Connor";$quoted = $db->quoteString($name); // "'John O\'Connor'"
$sql = "INSERT INTO users (name) VALUES (" . $quoted . ")";freeRecordSet
Section titled “freeRecordSet”釋放與結果相關的記憶體。
abstract public function freeRecordSet($result): void範例:
$result = $db->query($sql);// Process results...$db->freeRecordSet($result); // Free memory取得上次錯誤訊息。
abstract public function error(): string範例:
$result = $db->query($sql);if (!$result) { echo "Database error: " . $db->error();}取得上次錯誤號碼。
abstract public function errno(): int範例:
$result = $db->query($sql);if (!$result) { echo "Error #" . $db->errno() . ": " . $db->error();}預備語句(MySQLi)
Section titled “預備語句(MySQLi)”MySQLi 驅動程式支援預備語句以增強安全性。
prepare
Section titled “prepare”建立預備語句。
public function prepare(string $sql): mysqli_stmt|false範例:
$db = XoopsDatabaseFactory::getDatabaseConnection();
$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE uid = ?";$stmt = $db->prepare($sql);
$stmt->bind_param('i', $userId);$userId = 5;$stmt->execute();$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) { echo $row['uname'];}$stmt->close();具有多個參數的預備語句
Section titled “具有多個參數的預備語句”$sql = "INSERT INTO " . $db->prefix('articles') . " (title, content, author_id) VALUES (?, ?, ?)";$stmt = $db->prepare($sql);
$stmt->bind_param('ssi', $title, $content, $authorId);
$title = "My Article";$content = "Article content here";$authorId = 1;
if ($stmt->execute()) { echo "Article created with ID: " . $stmt->insert_id;}
$stmt->close();beginTransaction
Section titled “beginTransaction”開始交易。
public function beginTransaction(): boolcommit
Section titled “commit”提交目前的交易。
public function commit(): boolrollback
Section titled “rollback”回復目前的交易。
public function rollback(): bool範例:
$db = XoopsDatabaseFactory::getDatabaseConnection();
try { $db->beginTransaction();
// Multiple operations $sql1 = "UPDATE " . $db->prefix('accounts') . " SET balance = balance - 100 WHERE id = 1"; $db->queryF($sql1);
$sql2 = "UPDATE " . $db->prefix('accounts') . " SET balance = balance + 100 WHERE id = 2"; $db->queryF($sql2);
// Check for errors if ($db->errno()) { throw new Exception($db->error()); }
$db->commit(); echo "Transaction completed";
} catch (Exception $e) { $db->rollback(); echo "Transaction failed: " . $e->getMessage();}完整使用範例
Section titled “完整使用範例”基本 CRUD 操作
Section titled “基本 CRUD 操作”$db = XoopsDatabaseFactory::getDatabaseConnection();
// CREATE$sql = sprintf( "INSERT INTO %s (title, content, created) VALUES (%s, %s, %d)", $db->prefix('articles'), $db->quoteString('New Article'), $db->quoteString('Article content'), time());$db->queryF($sql);$articleId = $db->getInsertId();
// READ$sql = "SELECT * FROM " . $db->prefix('articles') . " WHERE id = " . (int)$articleId;$result = $db->query($sql);$article = $db->fetchArray($result);
// UPDATE$sql = sprintf( "UPDATE %s SET title = %s, updated = %d WHERE id = %d", $db->prefix('articles'), $db->quoteString('Updated Title'), time(), $articleId);$db->queryF($sql);
// DELETE$sql = "DELETE FROM " . $db->prefix('articles') . " WHERE id = " . (int)$articleId;$db->queryF($sql);function getArticles(int $page = 1, int $perPage = 10): array{ $db = XoopsDatabaseFactory::getDatabaseConnection(); $start = ($page - 1) * $perPage;
// Get total count $sql = "SELECT COUNT(*) as total FROM " . $db->prefix('articles') . " WHERE published = 1"; $result = $db->query($sql); $row = $db->fetchArray($result); $total = $row['total'];
// Get page of results $sql = "SELECT * FROM " . $db->prefix('articles') . " WHERE published = 1 ORDER BY created DESC"; $result = $db->query($sql, $perPage, $start);
$articles = []; while ($row = $db->fetchArray($result)) { $articles[] = $row; }
return [ 'articles' => $articles, 'total' => $total, 'pages' => ceil($total / $perPage), 'current' => $page ];}使用 LIKE 的搜尋查詢
Section titled “使用 LIKE 的搜尋查詢”function searchArticles(string $keyword): array{ $db = XoopsDatabaseFactory::getDatabaseConnection();
$keyword = $db->escape($keyword); $sql = "SELECT * FROM " . $db->prefix('articles') . " WHERE title LIKE '%" . $keyword . "%'" . " OR content LIKE '%" . $keyword . "%'" . " ORDER BY created DESC";
$result = $db->query($sql, 50); // Limit to 50 results
$articles = []; while ($row = $db->fetchArray($result)) { $articles[] = $row; }
return $articles;}Join 查詢
Section titled “Join 查詢”function getArticlesWithAuthors(): array{ $db = XoopsDatabaseFactory::getDatabaseConnection();
$sql = "SELECT a.*, u.uname as author_name, u.email as author_email FROM " . $db->prefix('articles') . " a LEFT JOIN " . $db->prefix('users') . " u ON a.author_id = u.uid WHERE a.published = 1 ORDER BY a.created DESC";
$result = $db->query($sql, 20);
$articles = []; while ($row = $db->fetchArray($result)) { $articles[] = $row; }
return $articles;}SqlUtility 類別
Section titled “SqlUtility 類別”SQL 檔案操作的協助程式類別。
splitMySqlFile
Section titled “splitMySqlFile”將 SQL 檔案分割為單個查詢。
public static function splitMySqlFile(string $content): array範例:
$sqlContent = file_get_contents('install.sql');$queries = SqlUtility::splitMySqlFile($sqlContent);
foreach ($queries as $query) { $db->queryF($query); if ($db->errno()) { echo "Error executing: " . $query . "\n"; echo "Error: " . $db->error() . "\n"; }}prefixQuery
Section titled “prefixQuery”使用首碼表格名稱替換表格預留位置。
public static function prefixQuery(string $sql, string $prefix): string範例:
$sql = "CREATE TABLE {PREFIX}_articles (id INT PRIMARY KEY)";$prefixedSql = SqlUtility::prefixQuery($sql, $db->prefix());// "CREATE TABLE xoops_articles (id INT PRIMARY KEY)"- 始終逃脫使用者輸入:
$safe = $db->escape($_POST['input']);- 在可用時使用預備語句:
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");$stmt->bind_param('i', $id);- 對值使用 quoteString:
$sql = "INSERT INTO table (name) VALUES (" . $db->quoteString($name) . ")";- 始終對大型表使用 LIMIT:
$result = $db->query($sql, 100); // Limit results- 在完成後釋放結果集:
$db->freeRecordSet($result);-
在表格定義中使用適當的索引
-
盡可能優先使用處理程式而不是原始 SQL
- 始終檢查錯誤:
$result = $db->query($sql);if (!$result) { trigger_error($db->error(), E_USER_WARNING);}- 對多個相關操作使用交易:
$db->beginTransaction();// ... operations ...$db->commit(); // or $db->rollback();- Criteria - 查詢條件系統
- QueryBuilder - 流暢查詢構建
- ../Core/XoopsObjectHandler - 物件持久化
另請參閱:XOOPS 原始程式碼