Eloquent ORM Trong Laravel Là Gì?

Eloquent ORM Trong Laravel Là Gì?
Trong bài chia sẻ này, các bạn sẽ tìm hiểu về Eloquent ORM trong Laravel và cách sử dụng Model như thế nào.

Laravel cung cấp 2 kiểu truy vấn thông dụng cho database là Eloquent ORM và Query Builder. Nếu Query Builder làm việc trực tiếp với database qua các truy vấn, thì Eloquent ORM sử dụng Model để tương tác với database. 

 

Định nghĩa Eloquent Model và các thiết lập cơ bản

 

ORM là gì?

 

ORM (Object Relational Mapping) là tên gọi chỉ việc ánh xạ các record dữ liệu trong một hệ quản trị cơ sở dữ liệu. Nó chuyển qua loại đối tượng mà mã nguồn đang định dạng trong class. 

 

Eloquent ORM là gì?

Eloquent ORM là thư viện ORM được cài kèm với Laravel nhằm cung cấp các phương thức truy xuất dữ liệu đơn giản. Do đó, các bạn dễ triển khai nó hơn. Mỗi bảng dữ liệu đều được mô tả thành một Model trong Laravel và Eloquent ORM ánh xạ các dữ liệu đó thành các đối tượng Active Record tương thích với model. Làm việc với các dữ liệu trở nên đơn giản hơn với các thao tác chính từ các Model này. 

 

Với mỗi Model, các bạn sẽ có 4 hành động tương ứng để quan tâm. Nó tương thích với 4 hoạt động của bản ghi dữ liệu (record):

 

  • Create: tạo ra 1 Model và tương ứng với việc tạo ra 1 bản ghi dữ liệu trong bảng
  • Read: truy vấn dữ liệu từ database và map lên Model
  • Update: chỉnh sửa 1 Model hoặc tương ứng là chỉnh sửa 1 bản ghi
  • Delete: xóa 1 Model và tương ứng là xóa 1 bản ghi dữ liệu

 

Với Eloquent ORM, Laravel đã sử dụng kỹ thuật ORM nhằm hỗ trợ các bạn thao tác nhanh gọn với DB. Trong bài này, các bạn sẽ tìm hiểu nhiều hơn về Eloquent Model. Đó là một phần trong mô hình MVC. Các Model đó sẽ thao tác trực tiếp với DB, xử lý logic nghiệp vụ và trả về với dữ liệu cho controller. 

 

Các bạn sẽ định nghĩa ra Model bằng câu lệnh make:model trong command Artisan như thế này: 

 

php artisan make:model Post

 

Sau khi các bạn nhấn lệnh, thì trong app/Post.php sẽ có dòng code sau:

 

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
    //
}

 

Để tạo Model và migration, các bạn nên bổ sung --migration hoặc -m

 

php artisan make:model Post --migration
php artisan make:model Post –m

 

Các bạn nên để tên Model đúng với mapping và bảng trong cơ sở dữ liệu. Nếu table trong cơ sở dữ liệu là post, thì tên Model phải đặt là post. 

 

Tên bảng 

 

Nếu bạn đặt tên Model là Post thì Laravel sẽ mapping với bảng tên là Posts. Nếu bạn muốn đặt tên khác cho bảng, thì bạn vẫn phải tuân thủ đúng quy chuẩn convention đặt tên trong Laravel. Ví dụ bạn có thể đặt tên bảng là my_posts, thì biến $table trong Illuminate\Database\Eloquent\Model sẽ mapping đúng model với tên bảng mà bạn đã khai báo.

 

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
    /**
     * The table associated with the model.
     *
     * @var  string
     */
    protected $table = 'my_posts';
}

 

Khóa chính của bảng 

 

Theo mặc định trong Laravel, khóa chính của mỗi bảng sẽ là id. Đôi khi, các bạn muốn thay đổi trường khóa chính này với tên khác (ví dụ là id_post). Lúc đó, bạn khai báo qua biến $primaryKey. 

 

protected $primaryKey = 'id_post';

 

Kiểu dữ liệu của khóa chính là int. Nếu bạn không muốn khóa chính của bạn tự tăng thì sẽ xảy ra hiện tượng: $incrementing = false. Nếu kiểu dữ liệu của khóa chính không phải là int, thì bạn nên tùy chỉnh thành biến $keyType = 'string'.

 

Timestamps

 

Khi các bạn tạo bảng thì sẽ thấy có 2 trường created_at và updated_at. Khi các bạn thêm các bản ghi vào table thì 2 trường này sẽ tự động cập nhật thêm. Để Eloquent không tự cập nhật giá trị cho 2 trường này, bạn thêm record thì sẽ cập nhật trong model như sau: 

 

public $timestamps = false;

 

Nếu bạn không muốn lưu dữ liệu của timestamps như mặc định của nó, thì bạn có thể thay đổi định dạng của nó trong model. 

 

protected $dateFormat = 'd-m-Y';

 

Nếu bạn muốn custom lại tên cột của timestamps, thì bạn nên thiết lập lại trong model. 

 

const CREATED_AT = 'creation_date';
const UPDATED_AT = 'last_update';

 

Kết nối DB

 

Tất cả Eloquent models sẽ sử dụng DB mặc định khai báo trong file .env. Tuy nhiên, bạn muốn model này kết nối đến 1 bảng trong cơ sở dữ liệu nào đó, thì bạn cần thiết lập trong model đó.

 

protected $connection = 'connection-name';

 

Insert dữ liệu 

 

Thêm 1 bản ghi dữ liệu sẽ tương ứng một thực thể hoặc một cài đặt (instance) từ Model. Ví dụ:

 

Bạn tạo 1 thực thể bằng câu lệnh new Ten_model và một thực thể $product từ Model Product. Sau đó, bạn gán giá trị cho các thuộc tính chung của chúng. Khi muốn lưu record vào database, thì bạn cần gọi phương thức save(). Các trường created_at và updated_at sẽ được cập nhật các giá trị thời gian một cách tự động và linh hoạt. Do đó, bạn chỉ quan tâm đến các trường này khi bạn sử dụng giá trị của chúng. 

 

Nếu không sử dụng Laravel Eloquent, thì bạn có thể chuyển qua Query Builder. Khi đó, các bạn phải tự chủ động giải quyết các công việc mà Laravel Eloquent đã ngầm mặc định là đưa vào giá trị thời gian cho created_at và updated_at chẳng hạn. Ví dụ:

 

// Code trích dẫn trong phương thức store của ProductController trong ví dụ Query Builder
$active = $request->has('active')? 1 : 0;
$product_id = DB::table('products')->insertGetId([
    'name'       => $request->input('name'),
    'price'      => $request->input('price'),
    'content'    => $request->input('content'),
    'image_path' => $request->input('image_path'),
    'active'     => $active,
    'created_at' => \Carbon\Carbon::now(),
    'updated_at' => \Carbon\Carbon::now()
]);

 

Model Mass Assignment là gì?

 

Model Mass Assignment có nguồn gốc từ ngôn ngữ Ruby on Rails, nghĩa là cho phép chúng ta lập trình tự động bằng cách gán các tham số của 1 HTTP request vào các biến hoặc đối tượng trong lập trình. Ví dụ bạn có 1 form đăng ký người dùng mà các tên trường nhập liệu trùng với tên cột trong bảng users của cơ sở dữ liệu. 

 

<form>
     <input name='username' type='text'>
     <input name='password' type='text'>
     <input name='email' type='text'>
     <input type=submit>
  </form>

 

Khi đó, form này post dữ liệu lên. Các bạn có thể ghi dữ liệu này vào cơ sở dữ liệu bằng dòng code sau: 

 

$user = new User(Input::all());

 

Tính năng Mass Assignment hỗ trợ các bạn tạo dòng code đơn giản và ngắn gọn. Tuy nhiên, nhược điểm của nó là tính bảo mật thấp. Nếu có kẻ xấu nào đó gửi thêm dữ liệu user_type = ‘admin’, thì user sẽ có thêm quyền admin. 

 

Việc gắn thêm dữ liệu gửi lên server là cực dễ. Kẻ xấu có thể sử dụng các công cụ có sẵn trên trình duyệt, ví dụ Chrome Developer Tools. Để vá lỗ hổng này, Laravel cung cấp thêm 2 thuộc tính cho Model là $fillable và $guarded. 

 

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model

{

    /**

     * The attributes that are mass assignable.

     *

     * @var  array

     */

    protected $fillable = ['name', 'password', 'email'];

}

 

$fillable cho phép các bạn thiết lập các cột trong 1 bảng để có thể sử dụng tính năng Mass Assignment. Khi đó, bạn thực hiện như sau: 

 

$user = User::create(Input::all());

// Hoặc

$user = new User(Input::al());

 

Nếu kẻ xấu gửi thêm user_type là trường không có trong $fillable, các câu lệnh trên sẽ có 1 exception. Do đó, lỗ hổng trong Mass Assignment đã được xử lý xong. Ngược lại với $fillable, các bạn có thể định nghĩa các trường được bảo vệ khỏi Mass Assignment thông qua thuộc tính $guarded. Bạn không nên khai báo cả 2 thuộc tính cùng lúc.

 

$fillable và $guarded chỉ có tác dụng với các phương thức của Eloquent Model. Các phương thức của Query Builder thì không có ứng dụng tương tự. Ví dụ:

 

// Phương thức Eloquent 

$user = User::find($id);

$user->update(Input::all());

// Phương thức Query Builder

User::where('id', $id)->update(Input::all());

 

Nếu kẻ xấu có chèn user_type = ‘admin’, thì đoạn code đầu sẽ phát sinh exception. Nhưng đoạn code sau thì vẫn hoạt động trơn tru. 

 

Một số phương thức tạo bản ghi bên ngoài 

 

Có 2 phương thức tạo bản ghi mới sử dụng Mass Assignment khác là firstOrCreate và firstOrNew. 

 

Phương thức firstOrCreate() thử tìm các bản ghi sử dụng một cặp cột và giá trị. Nếu không tìm thấy, 1 bản ghi sẽ được tự động tạo ra với các thuộc tính này. firstOrNew thì không ghi dữ liệu vào cơ sở dữ liệu mà nó trả về 1 instance của model và nó chỉ ghi dữ liệu xuống cơ sở dữ liệu khi bạn gọi phương thức save(). 

 

// Tìm user trong CSDL nếu không có thì insert bản ghi

$user = User::firstOrCreate(Input::all());

// Tìm user trong CSDL nếu không có thì trả về một instance của User và chỉ ghi xuống CSDL khi gọi phương thức save()

$user = User::firstOrCreate(Input::all());

$user->save();

 

Các bạn cũng sẽ thường gặp một phương thức khác. Đó là updateOrCreate. Nhiệm vụ của nó là tạo mới 1 entry hoặc cập nhật 1 entry đã có sẵn. Xem ví dụ sau: 

 

$product = Product::updateOrCreate(

    ['name' => 'Bộ phát WiFi TENDA FH304', 'active' => 1],

    ['price' => 750000]

);

 

Hồ Hữu Hiền

Mình là developer nên đôi khi viết bài không hay lắm mong các bạn thông cảm. Nếu muốn biết thêm thông tin về mình thì vui lòng vào website này để biết. https://huuhienqt.dev/

Bình luận (0)