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

Trình tạo truy vấn XOOPS

Trình tạo truy vấn XOOPS cung cấp giao diện hiện đại, trôi chảy để xây dựng các truy vấn SQL. Nó giúp ngăn chặn việc tiêm SQL, cải thiện khả năng đọc và cung cấp khả năng trừu tượng hóa cơ sở dữ liệu cho nhiều hệ thống cơ sở dữ liệu.

graph TD
A[QueryBuilder] -->|builds| B[SELECT Queries]
A -->|builds| C[INSERT Queries]
A -->|builds| D[UPDATE Queries]
A -->|builds| E[DELETE Queries]
F[Table] -->|chains| G[select]
F -->|chains| H[where]
F -->|chains| I[orderBy]
F -->|chains| J[limit]
G -->|chains| K[join]
G -->|chains| H
H -->|chains| I
I -->|chains| J
L[Execute Methods] -->|returns| M[Results]
L -->|returns| N[Count]
L -->|returns| O[First/Last]

Trình tạo truy vấn chính class với giao diện thông thạo.

namespace Xoops\Database;
class QueryBuilder
{
protected string $table = '';
protected string $type = 'SELECT';
protected array $selects = [];
protected array $joins = [];
protected array $wheres = [];
protected array $orders = [];
protected int $limit = 0;
protected int $offset = 0;
protected array $bindings = [];
}

Tạo trình tạo truy vấn mới cho một bảng.

public static function table(string $table): QueryBuilder

Thông số:

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

Trả về: QueryBuilder - Phiên bản trình tạo truy vấn

Ví dụ:

$query = QueryBuilder::table('users');
$query = QueryBuilder::table('xoops_users'); // With prefix

Chỉ định các cột để chọn.

public function select(...$columns): self

Thông số:

Tham sốLoạiMô tả
...$columnsmảngTên cột hoặc biểu thức

Trả về: self - Dành cho chuỗi phương thức

Ví dụ:

// Simple select
QueryBuilder::table('users')
->select('id', 'username', 'email')
->get();
// Select with aliases
QueryBuilder::table('users')
->select('id as user_id', 'username as name')
->get();
// Select all columns
QueryBuilder::table('users')
->select('*')
->get();
// Select with expressions
QueryBuilder::table('orders')
->select('id', 'COUNT(*) as total_items')
->groupBy('id')
->get();

Thêm điều kiện WHERE.

public function where(string $column, string $operator = '=', mixed $value = null): self

Thông số:

Tham sốLoạiMô tả
$columnchuỗiTên cột
$operatorchuỗiToán tử so sánh
$valuehỗn hợpGiá trị để so sánh

Trả về: self - Dành cho chuỗi phương thức

Người vận hành:

Nhà điều hànhMô tảVí dụ
=Bằng->where('status', '=', 'active')
!= hoặc <>Không bằng->where('status', '!=', 'deleted')
>Lớn hơn->where('price', '>', 100)
<Ít hơn->where('price', '<', 100)
>=Lớn hơn hoặc bằng->where('age', '>=', 18)
<=Ít hơn hoặc bằng->where('age', '<=', 65)
LIKEKhớp mẫu->where('name', 'LIKE', '%john%')
INTrong danh sách->where('status', 'IN', ['active', 'pending'])
NOT INKhông có trong danh sách->where('id', 'NOT IN', [1, 2, 3])
BETWEENPhạm vi->where('age', 'BETWEEN', [18, 65])
IS NULLLà vô giá trị->where('deleted_at', 'IS NULL')
IS NOT NULLKhông rỗng->where('deleted_at', 'IS NOT NULL')

Ví dụ:

// Single condition
QueryBuilder::table('users')
->select('*')
->where('status', '=', 'active')
->get();
// Multiple conditions (AND)
QueryBuilder::table('users')
->select('*')
->where('status', '=', 'active')
->where('age', '>=', 18)
->get();
// IN operator
QueryBuilder::table('products')
->select('*')
->where('category_id', 'IN', [1, 2, 3])
->get();
// LIKE operator
QueryBuilder::table('users')
->select('*')
->where('email', 'LIKE', '%@example.com')
->get();
// NULL check
QueryBuilder::table('users')
->select('*')
->where('deleted_at', 'IS NULL')
->get();

Thêm điều kiện OR.

public function orWhere(string $column, string $operator = '=', mixed $value = null): self

Ví dụ:

QueryBuilder::table('users')
->select('*')
->where('status', '=', 'active')
->orWhere('premium', '=', 1)
->get();
// SELECT * FROM users WHERE status = 'active' OR premium = 1

Các phương pháp thuận tiện cho IN/NOT IN.

public function whereIn(string $column, array $values): self
public function whereNotIn(string $column, array $values): self

Ví dụ:

QueryBuilder::table('posts')
->select('*')
->whereIn('status', ['published', 'scheduled'])
->get();
QueryBuilder::table('comments')
->select('*')
->whereNotIn('spam_score', [8, 9, 10])
->get();

Các phương pháp thuận tiện để kiểm tra NULL.

public function whereNull(string $column): self
public function whereNotNull(string $column): self

Ví dụ:

QueryBuilder::table('users')
->select('*')
->whereNotNull('verified_at')
->get();

Kiểm tra xem giá trị có nằm giữa hai giá trị hay không.

public function whereBetween(string $column, array $values): self

Ví dụ:

QueryBuilder::table('products')
->select('*')
->whereBetween('price', [10, 100])
->get();
QueryBuilder::table('orders')
->select('*')
->whereBetween('created_at', ['2024-01-01', '2024-12-31'])
->get();

Thêm INNER THAM GIA.

public function join(
string $table,
string $first,
string $operator = '=',
string $second = null
): self

Ví dụ:

QueryBuilder::table('posts')
->select('posts.*', 'users.username', 'categories.name')
->join('users', 'posts.user_id', '=', 'users.id')
->join('categories', 'posts.category_id', '=', 'categories.id')
->where('posts.published', '=', 1)
->get();

Các loại tham gia thay thế.

public function leftJoin(
string $table,
string $first,
string $operator = '=',
string $second = null
): self
public function rightJoin(
string $table,
string $first,
string $operator = '=',
string $second = null
): self

Ví dụ:

QueryBuilder::table('users')
->select('users.*', 'COUNT(posts.id) as post_count')
->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->groupBy('users.id')
->get();

Nhóm kết quả theo (các) cột.

public function groupBy(...$columns): self

Ví dụ:

QueryBuilder::table('orders')
->select('user_id', 'COUNT(*) as order_count', 'SUM(total) as total_spent')
->groupBy('user_id')
->get();
QueryBuilder::table('sales')
->select('department', 'region', 'SUM(amount) as total')
->groupBy('department', 'region')
->get();

Thêm điều kiện HAVING.

public function having(string $column, string $operator = '=', mixed $value = null): self

Ví dụ:

QueryBuilder::table('orders')
->select('user_id', 'COUNT(*) as order_count')
->groupBy('user_id')
->having('order_count', '>', 5)
->get();

Kết quả đơn hàng.

public function orderBy(string $column, string $direction = 'ASC'): self

Thông số:| Tham số | Loại | Mô tả | |----------|------|-------------| | $column | chuỗi | Cột sắp xếp theo | | $direction | chuỗi | ASC hoặc DESC |

Ví dụ:

// Single order
QueryBuilder::table('users')
->select('*')
->orderBy('created_at', 'DESC')
->get();
// Multiple orders
QueryBuilder::table('posts')
->select('*')
->orderBy('category_id', 'ASC')
->orderBy('created_at', 'DESC')
->get();
// Random order
QueryBuilder::table('quotes')
->select('*')
->orderBy('RAND()')
->get();

Kết quả giới hạn và bù trừ.

public function limit(int $limit): self
public function offset(int $offset): self

Ví dụ:

// Simple limit
QueryBuilder::table('posts')
->select('*')
->limit(10)
->get();
// Pagination
$page = 2;
$perPage = 20;
$offset = ($page - 1) * $perPage;
QueryBuilder::table('posts')
->select('*')
->limit($perPage)
->offset($offset)
->get();

Thực hiện truy vấn và trả về tất cả kết quả.

public function get(): array

Trả về: array - Mảng các hàng kết quả

Ví dụ:

$users = QueryBuilder::table('users')
->select('id', 'username', 'email')
->where('status', '=', 'active')
->orderBy('username')
->get();
foreach ($users as $user) {
echo $user['username'] . ' (' . $user['email'] . ')' . "\n";
}

Nhận được kết quả đầu tiên.

public function first(): ?array

Trả về: ?array - Hàng đầu tiên hoặc rỗng

Ví dụ:

$user = QueryBuilder::table('users')
->select('*')
->where('id', '=', 123)
->first();
if ($user) {
echo 'Found: ' . $user['username'];
}

Nhận được kết quả cuối cùng.

public function last(): ?array

Ví dụ:

$latestPost = QueryBuilder::table('posts')
->select('*')
->orderBy('created_at', 'DESC')
->last();

Nhận được số lượng kết quả.

public function count(): int

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

Ví dụ:

$activeUsers = QueryBuilder::table('users')
->where('status', '=', 'active')
->count();
echo "Active users: $activeUsers";

Kiểm tra xem truy vấn có trả về kết quả nào không.

public function exists(): bool

Trả về: bool - Đúng nếu có kết quả

Ví dụ:

if (QueryBuilder::table('users')->where('email', '=', 'test@example.com')->exists()) {
echo 'User already exists';
}

Nhận các giá trị tổng hợp.

public function aggregate(string $function, string $column): mixed

Ví dụ:

$maxPrice = QueryBuilder::table('products')
->aggregate('MAX', 'price');
$avgAge = QueryBuilder::table('users')
->aggregate('AVG', 'age');
$totalSales = QueryBuilder::table('orders')
->aggregate('SUM', 'total');

Chèn một hàng.

public function insert(array $values): bool

Ví dụ:

QueryBuilder::table('users')->insert([
'username' => 'john',
'email' => 'john@example.com',
'password' => password_hash('secret', PASSWORD_BCRYPT),
'created_at' => date('Y-m-d H:i:s')
]);

Chèn nhiều hàng.

public function insertMany(array $rows): bool

Ví dụ:

QueryBuilder::table('log_entries')->insertMany([
['action' => 'login', 'user_id' => 1, 'timestamp' => time()],
['action' => 'logout', 'user_id' => 2, 'timestamp' => time()],
['action' => 'update', 'user_id' => 3, 'timestamp' => time()]
]);

Cập nhật hàng.

public function update(array $values): int

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

Ví dụ:

// Update single user
QueryBuilder::table('users')
->where('id', '=', 123)
->update([
'email' => 'newemail@example.com',
'updated_at' => date('Y-m-d H:i:s')
]);
// Update multiple rows
QueryBuilder::table('posts')
->where('status', '=', 'draft')
->where('created_at', '<', date('Y-m-d', strtotime('-30 days')))
->update([
'status' => 'archived'
]);

Tăng hoặc giảm một cột.

public function increment(string $column, int $amount = 1): int
public function decrement(string $column, int $amount = 1): int

Ví dụ:

// Increment view count
QueryBuilder::table('posts')
->where('id', '=', 123)
->increment('views');
// Decrement stock
QueryBuilder::table('products')
->where('id', '=', 456)
->decrement('stock', 5);

Xóa hàng.

public function delete(): int

Trả về: int - Số hàng đã xóa

Ví dụ:

// Delete single record
QueryBuilder::table('comments')
->where('id', '=', 789)
->delete();
// Delete multiple records
QueryBuilder::table('log_entries')
->where('created_at', '<', date('Y-m-d', strtotime('-30 days')))
->delete();

Xóa tất cả các hàng khỏi bảng.

public function truncate(): bool

Ví dụ:

// Clear all sessions
QueryBuilder::table('sessions')->truncate();
QueryBuilder::table('products')
->select('id', 'name', QueryBuilder::raw('price * quantity as total'))
->get();
$recentPostIds = QueryBuilder::table('posts')
->select('id')
->where('created_at', '>', date('Y-m-d', strtotime('-7 days')))
->toSql();
$comments = QueryBuilder::table('comments')
->select('*')
->whereIn('post_id', $recentPostIds)
->get();
public function toSql(): string

Ví dụ:

$sql = QueryBuilder::table('users')
->select('id', 'username')
->where('status', '=', 'active')
->toSql();
echo $sql;
// SELECT id, username FROM xoops_users WHERE status = ?
<?php
/**
* Get posts with author and category info
*/
$posts = QueryBuilder::table('posts')
->select(
'posts.id',
'posts.title',
'posts.content',
'posts.created_at',
'users.username as author',
'categories.name as category'
)
->join('users', 'posts.user_id', '=', 'users.id')
->join('categories', 'posts.category_id', '=', 'categories.id')
->where('posts.published', '=', 1)
->orderBy('posts.created_at', 'DESC')
->limit(10)
->get();
foreach ($posts as $post) {
echo '<article>';
echo '<h2>' . htmlspecialchars($post['title']) . '</h2>';
echo '<p class="meta">By ' . htmlspecialchars($post['author']) . ' in ' . htmlspecialchars($post['category']) . '</p>';
echo '<p>' . htmlspecialchars($post['content']) . '</p>';
echo '</article>';
}
<?php
/**
* Paginated results
*/
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$perPage = 20;
$offset = ($page - 1) * $perPage;
// Get total count
$total = QueryBuilder::table('articles')
->where('status', '=', 'published')
->count();
// Get page results
$articles = QueryBuilder::table('articles')
->select('*')
->where('status', '=', 'published')
->orderBy('created_at', 'DESC')
->limit($perPage)
->offset($offset)
->get();
// Calculate pagination
$pages = ceil($total / $perPage);
// Display results
foreach ($articles as $article) {
echo '<div class="article">' . htmlspecialchars($article['title']) . '</div>';
}
// Display pagination links
if ($pages > 1) {
echo '<nav class="pagination">';
for ($i = 1; $i <= $pages; $i++) {
if ($i == $page) {
echo '<span class="current">' . $i . '</span>';
} else {
echo '<a href="?page=' . $i . '">' . $i . '</a>';
}
}
echo '</nav>';
}
<?php
/**
* Sales analysis
*/
// Total sales by region
$regionSales = QueryBuilder::table('orders')
->select('region', QueryBuilder::raw('SUM(total) as total_sales'), QueryBuilder::raw('COUNT(*) as order_count'))
->groupBy('region')
->orderBy('total_sales', 'DESC')
->get();
foreach ($regionSales as $region) {
echo $region['region'] . ': $' . number_format($region['total_sales'], 2) . ' (' . $region['order_count'] . ' orders)' . "\n";
}
// Average order value
$avgOrderValue = QueryBuilder::table('orders')
->aggregate('AVG', 'total');
echo 'Average order value: $' . number_format($avgOrderValue, 2);
  1. Sử dụng truy vấn được tham số hóa - QueryBuilder tự động xử lý liên kết tham số
  2. Phương thức chuỗi - Tận dụng giao diện trôi chảy để có mã dễ đọc
  3. Kiểm tra đầu ra SQL - Sử dụng toSql() để xác minh các truy vấn được tạo
  4. Sử dụng chỉ mục - Đảm bảo các cột được truy vấn thường xuyên được lập chỉ mục
  5. Giới hạn kết quả - Luôn sử dụng limit() cho các tập dữ liệu lớn
  6. Sử dụng Tổng hợp - Cho phép cơ sở dữ liệu thực hiện đếm/tổng hợp thay vì PHP
  7. Escape Output - Luôn thoát dữ liệu được hiển thị với htmlspecialchars()
  8. Hiệu suất chỉ mục - Theo dõi các truy vấn chậm và tối ưu hóa tương ứng
  • XoopsDatabase - Lớp cơ sở dữ liệu và các kết nối
  • Tiêu chí - Hệ thống truy vấn dựa trên Tiêu chí kế thừa
  • ../Core/XoopsObject - Tính bền vững của đối tượng dữ liệu
  • ../Module/Module-System - Hoạt động cơ sở dữ liệu mô-đun

Xem thêm: Cơ sở dữ liệu XOOPS API