Laravel Tutorial

Bài 22: Database trong Laravel

Trong Laravel, database được hỗ trợ rất là mạnh qua các lớp Query Builder và Eloment ORM. Đồng thời Laravel cũng hỗ trợ mọi người sử dụng được nhiều database, connection trên cùng một ứng dụng một cách đơn giản.

Mặc định, Laravel hỗ trợ các loại database sau:

  • MySQL 5.6+
  • PostgreSQL 9.4+
  • SQLite 3.8.8+
  • SQL Server 2017+

Nếu các bạn muốn sử dụng các loại database khác có thể tham khảo thêm các package bên thứ 3 cung cấp hoặc comment ở post này mình sẽ tìm giúp các bạn

1. Cấu hình

Tất cả các thông tin cấu hình liên quan đến database trong Laravel đều được đặt trong config/database.php. Trong file này chứa thông tin kết nối đến rất nhiều database và bạn có thể cấu hình connection nào là default. Hầu hết các thông tin cấu hình này đều được lấy từ .env.

Đối với cấu hình SQLite thì DB_DATABASE trong env chính là đường dẫn đến file sqlite của bạn

Đối với Microsoft SQL server thì bạn cần đảm bảo PHP của bạn phải có các extension sqlsrv và pdo_sqlsrv

Thông thường, các cấu hình đến database sẽ có các thông tin như host, database, username, password,… Nhưng nếu như bạn muốn cấu hình thông tin qua URL connection thì Laravel cũng hỗ trợ. Bằng cách bạn có thể đưa chúng vào trong DATABASE_URL trong env.

URL này sẽ có dạng:

driver://username:password@host:port/database?options

Trong đó:

  • driver là loại database bạn muốn kết nối.
  • username là thông tin user đăng nhập vào database.
  • password là thông tin password đăng nhập vào database.
  • host là thông tin host của database.
  • port là port của datasbe.
  • database là tên database mà bạn muốn kết nối.
  • options là các option bạn muốn config kèm theo.

Ví dụ:

mysql://root:password@127.0.0.1/forge?charset=UTF-8

2. Read-Write Database

Trong một số trường hợp bạn muốn sử dụng các kết nối riêng biệt cho các câu lệnh SELECT dữ liệu, các câu lệnh NSERT, UPDATE  DELETE lại sử dụng kết nối khác. Thì laravel cũng hộ trợ bạn làm điều đó (cái này rất tiện cho các hệ thống sử dụng Master – Slave).

Nếu bạn muốn cấu hình kết nối read-write này bạn có thể tham khảo config mẫu sau:

'mysql' => [
    'read' => [
        'host' => [
            '192.168.1.1',
            '196.168.1.2',
        ],
    ],
    'write' => [
        'host' => [
            '196.168.1.3',
        ],
    ],
    'sticky' => true,
    'driver' => 'mysql',
    'database' => 'database',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
],

Trong đósticky là key không bắt buộc, sticky quyết định các truy vấn sau câu lệnh write sẽ được thực thi vào connection nào trong request đó. Nếu sticky thiết lập là true thì sau câu lệnh write data, các câu lệnh read phía sau sẽ sử dụng connection đến host của DB write luôn (miễn là trên cùng một request)

3. Thực thi query đến database

Sau khi đã hoàn tất việc kết nối đến database, giờ các bạn có thể query đến database thông qua class DB (\Illuminate\Support\Facades\DB)

# SELECT

use Illuminate\Support\Facades\DB;

$users = DB::select("SELECT * FROM users where active = 1");

Trong trường hợp bạn muốn sử dụng prepare query bạn có thể sử dụng tham số thứ 2 là các giá trị binding vào query.

use Illuminate\Support\Facades\DB;

$users = DB::select("SELECT * FROM users where active = ?", [1]);

Lấy ra data trả về: select sẽ trả về một mảng data, trong đó mỗi một data sẽ là một stdClass

use Illuminate\Support\Facades\DB;

$users = DB::select("SELECT * FROM users where active = ?", [1]);

foreach ($users as $user) {
    echo $user->name;
}

Ngoài ra bạn cũng có thể binding data vào câu query bằng cách gán tên cho nó

use Illuminate\Support\Facades\DB;

$users = DB::select('select * from users where id = :id', ['id' => 1]);

# INSERT

use Illuminate\Support\Facades\DB;

DB::insert("insert into users (id, name) values (1, 'Marc')");

Hoặc bạn cũng có thể sử dụng binding query vào trong phương thức insert

use Illuminate\Support\Facades\DB;

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Marc']);

# UPDATE

use Illuminate\Support\Facades\DB;

$affected = DB::update("update users set votes = 100 where name = 'Anita'");

Hoặc bạn cũng có thể sử dụng binding query vào trong phương thức update

use Illuminate\Support\Facades\DB;

$affected = DB::update('update users set votes = ? where name = ?', [100, 'Anita']);

# DELETE

use Illuminate\Support\Facades\DB;

$deleted = DB::delete('delete from users');

Thực thi các câu lệnh chung

Ngoài các câu lệnh ở trên ra, nếu trong trường hợp bạn không muốn nhận giá trị trả về từ database khi thực thi câu lệnh, bạn có thể sử dụng phương thức statement để thực thi

use Illuminate\Support\Facades\DB;

DB::statement('drop table users');

Chỉ định connection

Để chỉ định connection thực thi query đến database. Bạn có thể sử dụng phương thức connection để chỉ định connection trước khi thực thi query

Ví dụ: Chỉ định connection đến kết nối sqlite

use Illuminate\Support\Facades\DB;

$users = DB::connection('sqlite')->select(...);

Chú ý: Connection name chính là array key của array connections trong file config/database.php

4. Listen Query Event

Nếu như bạn muốn lắng nghe các câu query trên Laravel, bạn có thể sử dụng phương thức listen

DB::listen(function ($query) {
    // $query->sql
    // $query->bindings
    // $query->time
});

Tuy nhiên để cho listen hoạt động tốt bạn nên đặt chúng vào trong một service provider nào đó

app/Providers/AppServicesProvider.php

use Illuminate\Support\Facades\DB;

...

public function boot()
{
    DB::listen(function ($query) {
        // $query->sql
        // $query->bindings
        // $query->time
    });
}

5. Thực thi database transactions

Nếu như bạn muốn thực thi nhiều query theo một transaction của database, bạn có thể sử dụng phương thức transaction

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');
    DB::delete('delete from posts');
});

Trong trường hợp bạn muốn xác định số lần thử lại transaction, bạn có thểm truyền vào tham số thứ hai tương ứng với số lần thực thi lại transaction. Nếu hết số lần thực thi lại mà transaction vẫn chưa hoàn thành thì Laravel sẽ raise ra một exception.

Ví dụ: Retry lại transaction 5 lần

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');
    DB::delete('delete from posts');
}, 5);

Ngoài cách trên thì bạn cũng có thể thực thi transaction một cách thủ công qua các phương thức như:

  • beginTransaction – Bắt đầu transaction.
  • rollBack – Thực thi rollback query.
  • commit – Thực thi commit query

Ví dụ

try {
    DB::beginTransaction();
    DB::update('update users set votes = 1');
    DB::delete('delete from posts');
    DB::commit();
} catch (Exception $exception) {
    DB::commit();
}

6. Kết nối đến database thông qua CLI

Để kết nối đến database qua CLI các bạn có thể sử dụng câu lệnh sau:

php artisan db

Đối với trường hợp các bạn cần chỉ định connection các bạn có thể truyền thêm argument vào command

Ví dụ: Kết nối đến connection mysql

php artisan db mysql

 

Leave a Comment