Trong rất nhiều các bài viết trước, chúng ta phải thực hiện việc cập nhật dữ liệu vào cơ sở dữ liệu một cách giả tưởng. Chờ đợi và giờ là lúc chúng ta cùng tìm hiểu làm việc với CSDL trong Laravel.
Nếu như bạn đã từng lập trình PHP hoặc các ngôn ngữ khác, kết nối đến CSDL là một trong những việc quan trọng, phần lớn các project đều phải có CSDL chứa dữ liệu cho dự án. Làm việc với CSDL trong Laravel hết sức đơn giản, Laravel hiện đang hỗ trợ 4 loại CSDL phổ biến hiện nay: MySQL (Oracle) đã chuyển lên MariaDB, Postgres, SQLite, SQL Server (Microsoft). Laravel hiện chưa hỗ trợ kết nối đến CSDL Oracle, tuy nhiên có rất nhiều các gói thư viện hỗ trợ kết nối đến Oracle trên Github, tôi sẽ có một bài riêng về Làm việc với CSDL Oracle trên Laravel.
Truy vấn đến CSDL trong Laravel có 3 phương thức là truy vấn SQL thuần túy, sử dụng Query Builder và sử dụng Laravel Model (Eloquent ORM). Trong bài viết này chúng ta sẽ tập trung vào cấu hình kết nối Laravel đến CSDL và sử dụng truy vấn SQL thuần túy để truy xuất dữ liệu.
Thiết lập cấu hình kết nối cơ sở dữ liệu trên Laravel
Trong bài viết Thiết lập cấu hình Laravel chúng ta cũng đã nói sơ qua về cấu hình kết nối CSDL, tất cả các thiết lập kết nối CSDL được đưa vào trong file config/database.php và kết hợp cùng với các biến môi trường được thiết lập trong file .env ở thư mục gốc của project. Ví dụ về một thiết lập trong .env và config/database.php:
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE='adshare'
DB_USERNAME='admin'
DB_PASSWORD=secret
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
...
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'adshare'),
'username' => env('DB_USERNAME', 'admin'),
'password' => env('DB_PASSWORD', '12345678'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
...
],
Laravel hỗ trợ các kiến trúc đa máy chủ CSDL, ví dụ trong hệ thống máy chủ đã định sẵn một máy chủ CSDL chuyên cho các tác vụ đọc dữ liệu và một máy chủ CSDL khác chuyên cho tác vụ ghi dữ liệu, chúng ta có thể thiết lập cấu hình như sau:
'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
...
'mysql' => [
'read' => [
'host' => '192.168.1.1',
],
'write' => [
'host' => '196.168.1.2'
],
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'adshare'),
'username' => env('DB_USERNAME', 'admin'),
'password' => env('DB_PASSWORD', '12345678'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
...
],
Các tác vụ đọc dữ liệu sẽ được chuyển đến máy chủ 192.168.1.1 và ghi dữ liệu được chuyển đến 192.168.1.2. Ngoài ra Laravel còn cho phép kết nối đến nhiều CSDL đồng thời, sử dụng phương thức connection() với tham số truyền vào là tên connection được khai báo trong config/database.php.
$users = DB::connection('foo')->select(...);
Raw SQL query trong Laravel
Facade DB cung cấp các phương thức để thực hiện truy xuất dữ liệu như sau: select(), insert(), update(), delete() và statement(). Chúng ta sẽ tìm hiểu lần lượt từng phương thức này.
Phương thức select()
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Danh sách người dùng trong hệ thống
*
* @return Response
*/
public function index()
{
$users = DB::select('select * from users where active = ?', [1]);
return view('user.index', ['users' => $users]);
}
}
Tham số thứ nhất của select() là một câu truy vấn SQL thuần túy, tham số thứ hai là các giá trị cần đưa vào câu truy vấn. Phương thức này sẽ trả về một mảng, mỗi kết quả trong mảng là một đối tượng StdClass trong PHP, để truy xuất vào các giá của kết quả sử dụng cú pháp như ví dụ dưới:
<table>
<tr>
<th>User ID</th>
<th>User name</th>
</tr>
@foreach($users as $user)
<tr>
<th>{{ $user-> id }}</th>
<th>{{ $user->name }}</th>
</tr>
@endforeach
<table>
Với id, name là các trường trong bảng users trong CSDL. Để truyền giá trị vào trong một câu truy vấn sử dụng ?, ví dụ:
$results = DB::select('select * from users where email = :email', ['email' => 'myemail@gmail.com']);
Phương thức insert()
Thực hiện đưa một bản ghi vào một bảng trong CSDL
DB::insert('insert into users (id, name) values (?, ?)', [13, 'FirebirD']);
Phương thức update()
Sử dụng để cập nhật dữ liệu vào một bản ghi có sẵn trong CSDL.
$updated = DB::update('update users set name = 'Đặng Kiên' where id = ?', [13]);
Phương thức delete()
Xóa các bản ghi khỏi CSDL
$deleted = DB::delete('delete from users where active = 0');
Phương thức statement()
Sử dụng để chạy bất kỳ một câu lệnh SQL nào.
DB::statement('drop table users');
Ví dụ sử dụng raw SQL query trong Laravel
Chắc bạn đang chờ đợi đến phần ví dụ, chúng ta quay lại với ví dụ đăng ký thành viên trong bài Laravel Form validate kiểm soát thông tin nhập liệu. Trong ví dụ này, chúng ta chưa làm gì ở phần lưu thông tin người dùng vào CSDL. (Bạn nào mới nên đọc lại Laravel Form validate kiểm soát thông tin nhập liệu để xem ví dụ đang làm đến đâu) Đầu tiên chúng ta thực hiện tạo một database tên laravel-test và tạo một bảng users như sau:
![](https://danatec.vn/wp-content/uploads/2023/03/a.png)
![](https://danatec.vn/wp-content/uploads/2023/03/b.png)
Ok, tiếp theo cấu hình kết nối đến database. Mở file config/database.php và thiết lập:
'mysql' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'laravel-test',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
Vì cài đặt trên máy dev, tôi vẫn để user root có mật khẩu mặc định là rỗng, để cấu hình cho nhanh đưa hết cấu hình vào config/database.php mà không qua file .env. Tiếp theo, chúng ta cập nhật phương thức storeUser() trong UserController (xem file app\Http\Controllers\UserController.php).
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Validator;
use DB;
class UserController extends Controller
{
//
public function showRegisterForm(){
return view('fontend.register');
}
public function storeUser(Request $request){
//dd($request->all());
$messages = [
'required' => 'Trường :attribute bắt buộc nhập.',
'email' => 'Trường :attribute phải có định dạng email'
];
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
'email' => 'required|email',
'password' => 'required|numeric|min:6|confirmed',
'website' => 'sometimes|required|url'
], $messages);
if ($validator->fails()) {
return redirect('register')
->withErrors($validator)
->withInput();
} else {
// Lưu thông tin vào database, phần này sẽ giới thiệu ở bài về database
$name = $request->input('name');
$email = $request->input('email');
$password = $request->input('password');
$website = $request->input('website');
DB::insert('insert into users (name, email, password, website) values (?, ?, ?, ?)', [$name, $email, $password, $website]);
return redirect('register')
->with('message', 'Đăng ký thành công.');
}
}
}
Truy cập http://laravel.dev/register và nhập thông tin đăng ký
![](https://danatec.vn/wp-content/uploads/2023/03/c.png)
Click đăng ký sau đó mở bảng users chúng ta thấy dữ liệu đã được cập nhật vào CSDL.
![](https://danatec.vn/wp-content/uploads/2023/03/d.png)
Quản lý transaction trong CSDL
Giao dịch (transaction) là một nhóm các hành động có thứ tự trên CSDL nhưng lại được người dùng xem như là một đơn vị thao tác duy nhất. Ví dụ: một giao dịch thanh toán trực tuyến cho một món hàng trên mạng sẽ bao gồm nhiều hành động trên CSDL:
- Trừ tiền từ tài khoản người dùng.
- Cộng tiền vào tài khoản nhà cung cấp.
- Giảm số lượng hàng trong kho.
Khi đó, bất kỳ một hành động nào bị lỗi sẽ dẫn đến giao dịch lỗi. Trong thực tế khi lập trình, người ta thường nhóm các nhiều các hành động trên CSDL vào thành một nhóm và thực hiện chúng như một giao dịch, nếu một hành động lỗi, hệ thống sẽ thực hiện các lệnh sao cho quay về trạng thái ban đầu (rollback). Laravel cũng hỗ trợ quản lý transaction, thực hiện chúng khá đơn giản với cú pháp:
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
}, 5)
Chú ý tham số thứ 2 của phương thức transaction() là số lần thử thực hiện lại khi gặp tình trạng deadlock. Ngoài ra bạn có thể thao tác quản lý transaction một cách thủ công như khi nào mới rollback hoặc khi nào mới commit một cách tùy ý:
DB::beginTransaction();
// Bắt đầu các hành động trên CSDL
...
//Gặp lỗi nào đó mới rollback
DB::rollBack();
...
//Commit dữ liệu khi hoàn thành kiểm tra
DB::commit();