Laravel là một framework PHP mạnh mẽ được ưa chuộng nhờ cú pháp rõ ràng, dễ đọc và khả năng mở rộng cao. Trong quá trình phát triển ứng dụng, có những trường hợp bạn cần thực hiện các truy vấn cơ sở dữ liệu phức tạp mà cú pháp của Eloquent hoặc Query Builder không đáp ứng được. Raw DB Query là công cụ hữu ích giúp chạy các truy vấn SQL thuần trực tiếp, đồng thời Laravel còn cung cấp nhiều hàm như DB::raw(), selectRaw(), groupByRaw(), orderByRaw() và havingRaw() để nhúng biểu thức SQL thuần vào trong các truy vấn xây dựng bằng Query Builder. Bài viết dưới đây sẽ hướng dẫn bạn cách sử dụng các hàm này với ví dụ cụ thể và những lưu ý cần thiết.
1. Tổng quan về Raw DB Query trong Laravel
Laravel cung cấp nhiều cách để tương tác với cơ sở dữ liệu, bao gồm:
- Eloquent ORM: Cho phép làm việc với cơ sở dữ liệu dưới dạng các model.
- Query Builder: Hỗ trợ xây dựng truy vấn một cách linh hoạt, dễ đọc.
- Raw DB Query: Cho phép chạy các câu lệnh SQL gốc trực tiếp khi cần tối ưu hoặc thực hiện các truy vấn phức tạp không thể mô hình hóa dễ dàng qua Eloquent/Query Builder.
Raw DB Query giúp bạn:
- Thực hiện các truy vấn phức tạp mà không bị giới hạn bởi cú pháp của framework.
- Tối ưu hóa hiệu năng khi cần truy vấn trực tiếp tận dụng sức mạnh của SQL gốc.
- Sử dụng các hàm, biểu thức và cú pháp đặc thù của từng hệ quản trị cơ sở dữ liệu.
Song song đó, các hàm như DB::raw(), selectRaw(), groupByRaw(), orderByRaw() và havingRaw() mở rộng khả năng của Query Builder, cho phép nhúng các biểu thức SQL thuần vào truy vấn một cách linh hoạt và dễ kiểm soát.
2. Các phương thức Raw DB Query cơ bản
Laravel hỗ trợ sử dụng Raw DB Query thông qua facade DB với các phương thức sau:
a. DB::select(), DB::insert(), DB::update(), DB::delete(), DB::statement()
- DB::select(): Dùng để thực hiện các truy vấn SELECT và trả về kết quả dưới dạng mảng các đối tượng.
$users = DB::select('SELECT * FROM users WHERE active = ?', [1]);
foreach ($users as $user) {
echo $user->name;
}- DB::insert(): Thực hiện truy vấn INSERT.
DB::insert('INSERT INTO users (name, email, password) VALUES (?, ?, ?)', [
'Nguyễn Văn A', 'nguyenvana@example.com', bcrypt('matkhau123')
]);- DB::update(): Thực hiện truy vấn UPDATE.
$affected = DB::update('UPDATE users SET active = ? WHERE id = ?', [1, 5]);- DB::delete(): Thực hiện truy vấn DELETE.
$deleted = DB::delete('DELETE FROM users WHERE id = ?', [5]);- DB::statement(): Thực hiện các truy vấn SQL không trả về kết quả, ví dụ như tạo bảng hoặc thay đổi cấu trúc cơ sở dữ liệu. Câu lệnh này thường được sử dụng trong migrations, khi muốn thay đổi cấu trúc của bảng và dữ liệu cũ cần update theo cấu trúc mới của bảng.
DB::statement('DROP TABLE IF EXISTS old_users');b. DB::raw()
Hàm DB::raw() cho phép nhúng các biểu thức SQL thuần vào trong các truy vấn do Query Builder tạo ra. Ví dụ:
$results = DB::table('posts')
->select(DB::raw('author_id, COUNT(*) as total_posts'))
->groupBy('author_id')
->get();
foreach ($results as $row) {
echo "Tác giả {$row->author_id} có {$row->total_posts} bài viết.<br>";
}Trong ví dụ trên, DB::raw() được sử dụng để tính số lượng bài viết của từng tác giả.
3. Các hàm selectRaw(), groupByRaw(), orderByRaw() và havingRaw()
Để tăng tính linh hoạt và dễ đọc cho truy vấn, Laravel cung cấp các hàm sau:
a. selectRaw()
Hàm selectRaw() cho phép bạn xây dựng các phần lựa chọn (SELECT) bằng câu lệnh SQL thuần mà không cần phải sử dụng DB::raw() bên trong mảng select. Điều này giúp mã nguồn trở nên gọn gàng hơn.
Ví dụ:
$users = DB::table('users')
->selectRaw('id, name, YEAR(created_at) as year')
->get();
foreach ($users as $user) {
echo "ID: {$user->id} - Tên: {$user->name} - Năm tạo: {$user->year}<br>";
}b. groupByRaw()
Hàm groupByRaw() cho phép bạn nhóm kết quả dựa trên biểu thức SQL thuần. Điều này hữu ích khi bạn cần sử dụng các hàm tính toán hoặc biểu thức phức tạp trong mệnh đề GROUP BY.
Ví dụ:
$results = DB::table('posts')
->selectRaw('author_id, COUNT(*) as total_posts')
->groupByRaw('author_id')
->get();
foreach ($results as $row) {
echo "Tác giả {$row->author_id} có {$row->total_posts} bài viết.<br>";
}c. orderByRaw()
Hàm orderByRaw() cho phép bạn sắp xếp kết quả truy vấn theo một biểu thức SQL thuần. Đây là cách hữu ích để sắp xếp phức tạp hoặc theo các biểu thức tính toán.
Ví dụ:
$posts = DB::table('posts')
->select('id', 'title', 'views')
->orderByRaw('views DESC')
->get();
foreach ($posts as $post) {
echo "Bài viết: {$post->title} - Lượt xem: {$post->views}<br>";
}d. havingRaw()
Hàm havingRaw() được sử dụng để lọc kết quả sau khi nhóm (GROUP BY) theo một biểu thức SQL thuần trong mệnh đề HAVING. Điều này rất hữu ích khi cần áp dụng điều kiện cho các hàm tổng hợp.
Ví dụ:
$results = DB::table('posts')
->selectRaw('author_id, COUNT(*) as total_posts')
->groupBy('author_id')
->havingRaw('COUNT(*) > ?', [5])
->get();
foreach ($results as $row) {
echo "Tác giả {$row->author_id} có {$row->total_posts} bài viết (nhiều hơn 5).<br>";
}4. Ưu điểm và hạn chế của Raw DB Query
Ưu điểm:
- Tối ưu hiệu năng: Cho phép tối ưu hóa các truy vấn phức tạp và tận dụng các tính năng đặc thù của SQL gốc.
- Linh hoạt: Các hàm như selectRaw(), groupByRaw(), orderByRaw() và havingRaw() giúp nhúng biểu thức SQL thuần một cách trực quan vào truy vấn.
- Đa dạng khả năng tương tác: Không bị giới hạn bởi cú pháp của Eloquent hay Query Builder thông thường.
Hạn chế:
- Nguy cơ bảo mật: Nếu không sử dụng tham số ràng buộc đúng cách, dễ dẫn đến SQL Injection.
- Mất đi tính trừu tượng: Truy vấn SQL gốc có thể khiến ứng dụng phụ thuộc vào một hệ quản trị cơ sở dữ liệu cụ thể.
- Khó bảo trì: Truy vấn phức tạp bằng SQL thuần có thể khó đọc và bảo trì so với cú pháp của Eloquent.
5. Một số lưu ý khi sử dụng Raw DB Query và các hàm Raw
- Luôn sử dụng tham số ràng buộc: Khi chèn dữ liệu vào truy vấn, hãy sử dụng mảng tham số để ngăn ngừa SQL Injection.
- Kiểm tra lỗi kỹ lưỡng: Xử lý các lỗi phát sinh từ truy vấn SQL thuần để đảm bảo ứng dụng hoạt động ổn định.
- Kết hợp với Eloquent/Query Builder: Sử dụng Raw DB Query chỉ khi thực sự cần thiết. Trong nhiều trường hợp, Eloquent và Query Builder đã đáp ứng đủ yêu cầu.
- Ghi chú rõ ràng: Với các truy vấn phức tạp, hãy thêm chú thích để người khác (và chính bạn trong tương lai) hiểu rõ ý nghĩa và mục đích của truy vấn.
6. Ví dụ kết hợp các hàm Raw
Giả sử bạn muốn thống kê số lượng bài viết của từng tác giả trong bảng posts và tính phần trăm bài viết của họ so với tổng số bài viết, bạn có thể sử dụng các hàm selectRaw(), groupByRaw(), orderByRaw() và havingRaw() như sau:
$totalPosts = DB::table('posts')->count();
$results = DB::table('posts')
->selectRaw('author_id, COUNT(*) as total_posts, ROUND((COUNT(*) / '.$totalPosts.') * 100, 2) as percentage')
->groupByRaw('author_id')
->havingRaw('COUNT(*) > ?', [5])
->orderByRaw('total_posts DESC')
->get();
foreach ($results as $row) {
echo "Tác giả {$row->author_id} có {$row->total_posts} bài viết, chiếm {$row->percentage}% tổng số bài viết.<br>";
}Trong ví dụ này:
- selectRaw(): Lựa chọn các cột cùng với biểu thức tính toán.
- groupByRaw(): Nhóm kết quả theo
author_id. - havingRaw(): Lọc ra những tác giả có số bài viết lớn hơn 5.
- orderByRaw(): Sắp xếp kết quả theo số bài viết giảm dần.
Kết luận
Raw DB Query trong Laravel, cùng với các hàm như DB::raw(), selectRaw(), groupByRaw(), orderByRaw() và havingRaw(), mang đến cho bạn sức mạnh để thực hiện các truy vấn SQL phức tạp và tối ưu hóa hiệu năng ứng dụng. Tuy nhiên, cần cân nhắc kỹ lưỡng về bảo mật và khả năng bảo trì khi sử dụng các truy vấn này. Hy vọng với những hướng dẫn và ví dụ cụ thể ở trên, bạn đã có cái nhìn tổng quan và sẵn sàng áp dụng vào dự án của mình.
Nếu có bất kỳ thắc mắc hoặc góp ý nào, hãy để lại bình luận trên codetuthub.com. Chúc bạn thành công và có những trải nghiệm tuyệt vời cùng Laravel!









