Bỏ qua để đến nội dung

Lớp cơ sở dữ liệu Xoops

XoopsDatabase class cung cấp lớp trừu tượng hóa cơ sở dữ liệu cho XOOPS, xử lý quản lý kết nối, thực hiện truy vấn, xử lý kết quả và xử lý lỗi. Nó hỗ trợ nhiều trình điều khiển cơ sở dữ liệu thông qua kiến ​​trúc trình điều khiển.

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
// Recommended: Use the factory
$db = XoopsDatabaseFactory::getDatabaseConnection();
// Alternative: Direct singleton access
$db = XoopsDatabase::getInstance();
// Legacy: Use global variable
global $xoopsDB;

Thiết lập kết nối cơ sở dữ liệu.

abstract public function connect(bool $selectdb = true): bool

Thông số:

Tham sốLoạiMô tả
$selectdbboolCó nên chọn cơ sở dữ liệu

Trả về: bool - Đúng khi kết nối thành công

Ví dụ:

$db = XoopsDatabaseFactory::getDatabaseConnection();
if ($db->connect()) {
echo "Connected successfully";
}

Thực hiện truy vấn SQL.

abstract public function query(
string $sql,
int $limit = 0,
int $start = 0
): mixed

Thông số:

Tham sốLoạiMô tả
$sqlchuỗiChuỗi truy vấn SQL
$limitintSố hàng tối đa cần trả về (0 = không giới hạn)
$startintBắt đầu bù đắp

Trả về: resource|bool - Tài nguyên kết quả hoặc sai khi thất bại

Ví dụ:

$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 20

Thực hiện truy vấn buộc thực hiện thao tác (bỏ qua kiểm tra bảo mật).

public function queryF(string $sql, int $limit = 0, int $start = 0): mixed

Trường hợp sử dụng:

  • Các thao tác CHÈN, CẬP NHẬT, XÓA
  • Khi bạn cần bỏ qua các hạn chế chỉ đọc

Ví dụ:

$sql = sprintf(
"UPDATE %s SET views = views + 1 WHERE article_id = %d",
$db->prefix('articles'),
$articleId
);
$db->queryF($sql);

tiền tố ###

Thêm tiền tố bảng cơ sở dữ liệu.

public function prefix(string $table = ''): string

Thông số:

Tham sốLoạiMô tả
$tablechuỗiTên bảng không có tiền tố

Trả về: string - Tên bảng có tiền tố

Ví dụ:

$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)

Tìm nạp một hàng kết quả dưới dạng một mảng kết hợp.

abstract public function fetchArray($result): ?array

Thông số:

Tham sốLoạiMô tả
$resulttài nguyênTài nguyên kết quả truy vấn

Trả về: array|null - Mảng kết hợp hoặc null nếu không còn hàng

Ví dụ:

$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";
}

Lấy một hàng kết quả làm đối tượng.

abstract public function fetchObject($result): ?object

Thông số:

Tham sốLoạiMô tả
$resulttài nguyênTài nguyên kết quả truy vấn

Trả về: object|null - Đối tượng có thuộc tính cho mỗi cột

Ví dụ:

$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;
}

Tìm nạp một hàng kết quả dưới dạng một mảng số.

abstract public function fetchRow($result): ?array

Ví dụ:

$sql = "SELECT uname, email FROM " . $db->prefix('users');
$result = $db->query($sql);
while ($row = $db->fetchRow($result)) {
echo "Username: " . $row[0] . ", Email: " . $row[1];
}

Tìm nạp một hàng kết quả dưới dạng cả mảng kết hợp và mảng số.

abstract public function fetchBoth($result): ?array

Ví dụ:

$result = $db->query($sql);
$row = $db->fetchBoth($result);
echo $row['uname']; // By name
echo $row[0]; // By index

Lấy số hàng trong một tập kết quả.

abstract public function getRowsNum($result): int

Thông số:

Tham sốLoạiMô tả
$resulttài nguyênTài nguyên kết quả truy vấn

Trả về: int - Số lượng hàng

Ví dụ:

$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE level > 0";
$result = $db->query($sql);
$count = $db->getRowsNum($result);
echo "Found $count active users";

Lấy số lượng hàng bị ảnh hưởng từ truy vấn cuối cùng.

abstract public function getAffectedRows(): int

Trả về: int - Số lượng hàng bị ảnh hưởng

Ví dụ:

$sql = "UPDATE " . $db->prefix('users') . " SET last_login = " . time() . " WHERE uid = 1";
$db->queryF($sql);
$affected = $db->getAffectedRows();
echo "Updated $affected rows";

Lấy ID được tạo tự động từ INSERT cuối cùng.

abstract public function getInsertId(): int
```**Trả về:** `int` - ID chèn cuối cùng
**Ví dụ:**
```php
$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";

Thoát khỏi một chuỗi để sử dụng an toàn trong các truy vấn SQL.

abstract public function escape(string $string): string

Thông số:

Tham sốLoạiMô tả
$stringchuỗiChuỗi để thoát

Trả về: string - Chuỗi thoát (không có dấu ngoặc kép)

Ví dụ:

$unsafeInput = "O'Reilly";
$safe = $db->escape($unsafeInput); // "O\'Reilly"
$sql = "SELECT * FROM " . $db->prefix('users') . " WHERE uname = '" . $safe . "'";

Thoát và trích dẫn một chuỗi cho SQL.

public function quoteString(string $string): string

Thông số:

Tham sốLoạiMô tả
$stringchuỗiChuỗi để trích dẫn

Trả về: string - Chuỗi thoát và trích dẫn

Ví dụ:

$name = "John O'Connor";
$quoted = $db->quoteString($name); // "'John O\'Connor'"
$sql = "INSERT INTO users (name) VALUES (" . $quoted . ")";

Giải phóng bộ nhớ liên quan đến kết quả.

abstract public function freeRecordSet($result): void

Ví dụ:

$result = $db->query($sql);
// Process results...
$db->freeRecordSet($result); // Free memory

lỗi ###

Nhận được thông báo lỗi cuối cùng.

abstract public function error(): string

Ví dụ:

$result = $db->query($sql);
if (!$result) {
echo "Database error: " . $db->error();
}

Lấy số lỗi cuối cùng.

abstract public function errno(): int

Ví dụ:

$result = $db->query($sql);
if (!$result) {
echo "Error #" . $db->errno() . ": " . $db->error();
}

Trình điều khiển MySQLi hỗ trợ các câu lệnh đã chuẩn bị sẵn để tăng cường bảo mật.

Tạo một tuyên bố chuẩn bị.

public function prepare(string $sql): mysqli_stmt|false

Ví dụ:

$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();

Câu lệnh được chuẩn bị sẵn với nhiều tham số

Phần tiêu đề “Câu lệnh được chuẩn bị sẵn với nhiều tham số”
$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();

Bắt đầu một giao dịch.

public function beginTransaction(): bool

Cam kết giao dịch hiện tại.

public function commit(): bool

Khôi phục giao dịch hiện tại.

public function rollback(): bool

Ví dụ:

$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();
}

$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
];
}
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;
}
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;
}

Trình trợ giúp class cho các thao tác với tệp SQL.

Chia tệp SQL thành các truy vấn riêng lẻ.

public static function splitMySqlFile(string $content): array

Ví dụ:

$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";
}
}

Thay thế phần giữ chỗ của bảng bằng tên bảng có tiền tố.

public static function prefixQuery(string $sql, string $prefix): string

Ví dụ:

$sql = "CREATE TABLE {PREFIX}_articles (id INT PRIMARY KEY)";
$prefixedSql = SqlUtility::prefixQuery($sql, $db->prefix());
// "CREATE TABLE xoops_articles (id INT PRIMARY KEY)"

  1. Luôn thoát khỏi thao tác nhập của người dùng:
$safe = $db->escape($_POST['input']);
  1. Sử dụng các câu đã chuẩn bị sẵn nếu có:
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param('i', $id);
  1. Sử dụng quoteString cho các giá trị:
$sql = "INSERT INTO table (name) VALUES (" . $db->quoteString($name) . ")";
  1. Luôn sử dụng LIMIT cho các bảng lớn:
$result = $db->query($sql, 100); // Limit results
  1. Bộ kết quả miễn phí khi hoàn thành:
$db->freeRecordSet($result);
  1. Sử dụng các chỉ mục thích hợp trong định nghĩa bảng của bạn

  2. Ưu tiên các trình xử lý hơn SQL thô khi có thể

  1. Luôn kiểm tra lỗi:
$result = $db->query($sql);
if (!$result) {
trigger_error($db->error(), E_USER_WARNING);
}
  1. Sử dụng giao dịch cho nhiều hoạt động liên quan:
$db->beginTransaction();
// ... operations ...
$db->commit(); // or $db->rollback();
  • Tiêu chí - Hệ thống tiêu chí truy vấn
  • QueryBuilder - Xây dựng truy vấn thông thạo
  • ../Core/XoopsObjectHandler - Tính bền vững của đối tượng

Xem thêm: Mã nguồn XOOPS