1. Eloquent ORM là gì?

Eloquent ORM là ORM được tích hợp sẵn trong Laravel, sử dụng mô hình Active Record để tương tác với database.

Eloquent cho phép developer làm việc với dữ liệu thông qua các Model trong PHP thay vì phải viết SQL thủ công cho mọi thao tác. Mỗi model thường tương ứng với một bảng database, còn mỗi instance của model đại diện cho một bản ghi.

Ví dụ, database có bảng users:

CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255),
    email VARCHAR(255)
);

Trong Laravel, ta tạo model User:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected $fillable = [
        'name',
        'email',
    ];
}

Thay vì tự viết câu SQL INSERT, ta có thể sử dụng:

$user = User::create([
    'name' => 'Alice',
    'email' => '[email protected]',
]);

Eloquent chịu trách nhiệm xây dựng truy vấn, thực thi database operation và ánh xạ kết quả thành model.

2. Model và các quy ước của Eloquent

Model là thành phần trung tâm của Eloquent. Model thường nằm trong thư mục app/Models và kế thừa từ Illuminate\Database\Eloquent\Model.

Eloquent sử dụng một số quy ước mặc định để giảm cấu hình thủ công:

  • Model User mặc định ánh xạ đến bảng users.
  • Model Post mặc định ánh xạ đến bảng posts.
  • Primary key mặc định là id.
  • Các bảng thường có created_at và updated_at để Eloquent quản lý thời gian tạo, cập nhật.
  • Tên thuộc tính PHP như createdAt không nhất thiết phải giống tên column database; Eloquent hỗ trợ quy ước ánh xạ tên thông thường và cấu hình tùy chỉnh.

Nếu database sử dụng bảng hoặc khóa khác quy ước, có thể cấu hình trong model:

class User extends Model
{
    protected $table = 'app_users';

    protected $primaryKey = 'user_id';

    public $timestamps = false;
}

Trong ví dụ này, Eloquent sử dụng bảng app_users, khóa chính user_id và không tự quản lý timestamp.

3. Eloquent Query Builder – Xây dựng truy vấn

Eloquent cung cấp một API dạng fluent interface, cho phép nối nhiều điều kiện thành một truy vấn dễ đọc.

Ví dụ:

$posts = Post::query()
    ->where('status', 'published')
    ->where('views', '>=', 100)
    ->orderByDesc('created_at')
    ->limit(20)
    ->get();

Đoạn code này biểu diễn các bước lọc dữ liệu, sắp xếp và giới hạn kết quả. SQL cuối cùng vẫn được Laravel xây dựng và gửi đến database.

Ví dụ, API chỉ cần lấy ID và tên bài viết:

$posts = Post::query()
    ->select(['id', 'title'])
    ->where('status', 'published')
    ->get();

Cách này tránh truy xuất những column không cần thiết.

firstOrCreate() và updateOrCreate()

Eloquent còn hỗ trợ các thao tác kết hợp tìm kiếm và ghi dữ liệu:

$user = User::firstOrCreate(
    ['email' => '[email protected]'],
    ['name' => 'Alice']
);

Nếu tìm thấy user có email tương ứng, Eloquent trả về bản ghi đó. Nếu không tìm thấy, Eloquent tạo bản ghi mới với các thuộc tính được cung cấp.

updateOrCreate() có thể tìm bản ghi theo điều kiện rồi cập nhật hoặc tạo mới nếu chưa tồn tại:

$user = User::updateOrCreate(
    ['email' => '[email protected]'],
    ['name' => 'Alice Nguyen']
);

4. Accessors, Mutators và Attribute Casting

Eloquent có các cơ chế để chuyển đổi giá trị thuộc tính khi đọc hoặc gán dữ liệu.

Attribute Casting

Casting chuyển kiểu dữ liệu khi truy cập thuộc tính model.

protected function casts(): array
{
    return [
        'is_active' => 'boolean',
        'metadata' => 'array',
        'published_at' => 'datetime',
        'password' => 'hashed',
    ];
}

Ví dụ, column is_active có thể được lưu dưới dạng số 0 hoặc 1 trong database, nhưng khi truy cập model, Eloquent chuyển thành kiểu boolean.

Với metadata lưu JSON, casting array giúp thao tác dữ liệu thuận tiện hơn:

$post->metadata = [
    'featured' => true,
    'views' => 100,
];

$post->save();

Casting hashed giúp Laravel băm giá trị mật khẩu khi gán theo cơ chế hỗ trợ của framework; đây không phải mã hóa có thể giải ngược.

Accessor

Accessor chuyển đổi giá trị khi đọc thuộc tính.

use Illuminate\Database\Eloquent\Casts\Attribute;

protected function name(): Attribute
{
    return Attribute::make(
        get: fn (string $value) => ucfirst($value),
    );
}

Khi truy cập $user->name, Eloquent áp dụng logic getter đã khai báo.

Mutator

Mutator chuyển đổi giá trị khi gán thuộc tính:

protected function email(): Attribute
{
    return Attribute::make(
        set: fn (string $value) => strtolower($value),
    );
}

Khi gán email cho model, mutator chuẩn hóa giá trị thành chữ thường trước khi lưu theo cơ chế của Eloquent.

Casting, accessor và mutator có thể làm model dễ sử dụng hơn, nhưng không nên đưa quá nhiều logic nghiệp vụ phức tạp vào những cơ chế này. Chúng phù hợp nhất cho việc chuyển đổi hoặc chuẩn hóa thuộc tính.

5. Soft Delete – Xóa mềm

Soft delete cho phép đánh dấu một bản ghi là đã xóa thay vì xóa vật lý ngay lập tức khỏi database.

Trong model:

use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;
}

Migration tương ứng cần có column deleted_at, thường được khai báo bằng:

$table->softDeletes();

Khi gọi:

$post->delete();

Eloquent cập nhật thời điểm xóa thay vì xóa vật lý bản ghi. Các truy vấn Eloquent thông thường sẽ tự động loại những bản ghi đã bị soft delete.

Truy vấn bao gồm cả bản ghi đã xóa mềm:

$posts = Post::withTrashed()->get();

Chỉ lấy những bản ghi đã xóa mềm:

$posts = Post::onlyTrashed()->get();

Khôi phục:

$post->restore();

Xóa vật lý:

$post->forceDelete();

Soft delete hữu ích khi cần khôi phục dữ liệu hoặc lưu dấu lịch sử, nhưng cũng có nghĩa bản ghi vẫn tồn tại trong database.

6. Eloquent Events và Observers

Eloquent cung cấp các model events, chẳng hạn creating, created, updating, updated, saving, saved, deleting và deleted.

Các event này hữu ích khi cần thực hiện logic gắn với vòng đời của model, ví dụ chuẩn hóa dữ liệu hoặc ghi nhận hoạt động của bản ghi. Khi logic cần được tái sử dụng hoặc số lượng event handler tăng lên, có thể tổ chức chúng trong Observer thay vì dồn mọi xử lý vào controller.

Tuy nhiên, không nên coi model events là cơ chế thay thế cho transaction hay constraint. Một số thao tác mass update và mass delete không tải từng model nên không phát ra các event tương ứng cho từng bản ghi.

7. Tổng kết

Eloquent ORM là một trong những thành phần cốt lõi của Laravel, giúp thao tác với database thông qua Model và một API thống nhất.

Những kiến thức trọng tâm nhất nên nắm vững là:

  • Model và quy ước ánh xạ bảng, column, primary key và timestamp.
  • CRUD và cách sử dụng Query Builder.
  • Mass assignment với $fillable hoặc $guarded.
  • Relationship: hasOne, belongsTo, hasMany, belongsToMany.
  • Lazy loading, eager loading và cách phòng tránh N+1.
  • Attribute casting, accessors, mutators và query scopes.
  • Soft delete, transaction, pagination và xử lý dữ liệu lớn.
  • Model events, API Resources, SQL injection và tối ưu truy vấn.

Bài viết khác

locking & dead lock (Transaction)

1. Locking là gì? Locking (cơ chế khóa) là cơ chế database sử dụng để kiểm soát việc nhiều transaction cùng truy cập hoặc thay đổi dữ liệu, nhằm tránh những xung đột có thể làm sai lệch kết quả. Trong một ứng dụng có nhiều user, nhiều request có thể đồng thời thao tác […]

ORM

ORM là gì? (Object-Relational Mapping) Trong quá trình phát triển Backend, ứng dụng thường xuyên cần tương tác với database để lưu trữ, truy vấn, cập nhật và xóa dữ liệu. Một cách phổ biến để thực hiện những thao tác này là viết SQL trực tiếp. Tuy nhiên, khi dự án phát triển, việc […]

UAT(Kiểm thử chấp nhận người dùng)

UAT là gì? Trong toàn bộ Vòng đời phát triển phần mềm (SDLC), sau khi trải qua hàng loạt các cấp độ kiểm thử kỹ thuật nội bộ như Unit Testing, Integration Testing, System Testing, sản phẩm phần mềm vẫn chưa thể chính thức phát hành. Bước đệm cuối cùng và mang tính chất quyết […]

N+1 Query Problem

N+1 Query Problem là gì? Trong quá trình phát triển Backend, ứng dụng thường cần truy xuất dữ liệu từ database để trả về cho client. Một API có thể cần lấy danh sách đơn hàng cùng thông tin khách hàng tương ứng. Tuy nhiên, nếu ứng dụng truy vấn dữ liệu liên quan riêng […]

Transactions & ACID

Transactions & ACID là gì? Trong Backend, một request gửi đến API có thể yêu cầu hệ thống thực hiện nhiều thao tác trên database. Chẳng hạn, khi khách hàng đặt hàng, hệ thống có thể cần tạo đơn hàng, lưu chi tiết đơn hàng và cập nhật số lượng tồn kho. Nếu một thao […]

ORM – Object-Relational Mapping Fundamentals

1. ORM là gì? ORM (Object-Relational Mapping) là kỹ thuật ánh xạ giữa các đối tượng trong chương trình và dữ liệu được lưu trữ trong cơ sở dữ liệu quan hệ. Trong ứng dụng backend, dữ liệu thường được biểu diễn bằng struct hoặc object trong code, trong khi database lưu dữ liệu dưới […]

Leave a Reply

Your email address will not be published. Required fields are marked *