Header Ads Widget

Sử dụng relationships model trong Laravel

PHP Framework có một cách tạo relationships model khác nhau

Hầu hết các PHP Framework hiện nay đều được tích hợp relationships model, trong Yii Framework khái niệm này được gọi là Active Records, còn trong Laravel thì được gọi là Eloquent Object-Relational Mapper.

Trong các PHP Framework hiện nay, một khi chúng ta đã sử dụng Relationships Model thì khi chúng ta sử dụng model để lấy dữ liệu thì các dữ liệu trên các bảng relation cũng sẽ được lấy theo, chính vì thế điều này làm giảm performance của ứng dụng, đó là lý do vì sao có sự so sánh khi sử dụng câu lệnh SQL thuần hay là sử dụng Relationships Model?


Laravel Framework có 3 loại relation căn bản, cũng giống như hầu hết các PHP Framework là:
- One To One
- One To Many
- Many To Many

1. One To One

Đây là một kiểu relation cơ bản nhất trong dữ liệu của chúng ta. Ví dụ khi phân tích bảng users chẳng hạn, các bạn có thể lưu thông tin của user vào table users và sẽ lưu thông tin email của user này vào bảng emails chẳng hạn. Lý do là vì chúng ta muốn tập trung email vào một chổ, với lại không phải cứ có user là có email, chẳng hạn chúng ta muốn các email mà chúng ta lụm lặt được ở đâu đó cho vào bảng này luôn thì sao đúng không? Thì lúc này để liên kết được 2 bảng lại với nhau chúng ta sẽ cần một cái khóa ngoại (foreign key) để chỉ định là à thằng user này có cái user_id này mày có cái email ở bảng emails này.
Như vậy lúc này trong Laravel Framework chúng ta cần phải có tận 2 model để mô tả cho sự liên kết này.

Tạo User model:
1
2
3
4
5
6
7
8
9
10
<?php
class User extends Eloquent{
    protected $table = 'users';
    public $timestamps = false;
    protected $guarded = array();
     
    public function email(){
        return $this->hasOne('Email');
    }
}
Email model:
1
2
3
4
5
6
7
8
9
10
<?php
class Email extends Eloquent{
    protected $table = 'emails';
    public $timestamps = false;
    protected $guarded = array();
     
    public function user(){
        return $this->belongsTo('User');
    }
}
One To One thì 2 table có vai trò là như nhau, chỉ khi chúng ta chỉ định foreign key nằm trên table nào thì table kia mới là table chính, ở ví dụ này ta nên đặt table User là table chính, trên table emails chúng ta sẽ có một foreign key là user_id để chỉ ra sự liên kết giữa table users và emails.
Vậy trong table chính chúng ta sẽ sử dụng phương thức là hasOne và trỏ đến table phụ, còn trong table phụ để chỉ định rằng email này là của user nào thì chúng ta sử dụng phương thức belongsTo.
Bây giờ chúng ta sẽ lấy dữ liệu lên xem thế nào nhé, việc lấy dữ liệu của relation rất là dễ chúng ta chỉ cần:
1
2
$email = User::find(1)->email;
print_r($email);
Tất nhiên là nếu không có user với id là 1 thì một lỗi sẽ được quăng ra, khi viết code các bạn cần chú ý chổ này.
Cách lấy user từ email cũng tương tự:
1
2
$user = Email::find(1)->user;
print_r($user);

Mặc định thì user_id sẽ được sử dụng làm foreign key, tuy nhiên các bạn cũng có thể chỉ định field nào trên table phụ làm foreign key, chúng ta chỉ cần:
1
2
3
4
5
6
7
8
9
class User extends Eloquent{
    protected $table = 'users';
    public $timestamps = false;
    protected $guarded = array();
     
    public function email(){
        return $this->hasOne('Email', 'custom_user_id');
    }
}

2. One To Many

One To Many - Cái này có vẻ như chúng ta thường gặp khi thao tác với cơ sở dữ liệu nhất, một danh mục thì có nhiều sản phẩm, một sản phẩm thì có nhiều comment, một comment thì có những ai đã like,...

Trong Laravel việc định nghĩa loại relationship này cũng không có gì khó khăn cả, tương tự như trên mà thôi, chúng ta chỉ cần một phương thức là hasMany mà thôi, ok ta sẽ có một ví dụ sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class Cate extends Eloquent{
 
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'cates';
    public $timestamps = false;
    protected $guarded = array();
     
    public function products(){
        return $this->hasMany('Product');
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
class Product extends Eloquent {
 
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'products';
    public $timestamps = false;
    protected $guarded = array();
     
    public function cate()
    {
        return $this->belongsTo('Cate');
    }
}
1
2
$products = Cate::find(1)->products;
print_r($products);
1
2
3
4
5
$cate = Product::find(2)->cate;
print_r($cate);

3. Many To Many

Đây là một kiểu relationship sử dụng cơ chế phân quyền ứng dụng, chúng ta thường quản lý user theo role, một role sẽ có nhiều users, tuy nhiên đôi khi các bạn muốn nâng cao hơn tí, đó là một user có thể thuộc nhiều role chẳng hạn, đây chính là kiểu relation many to many mà chúng ta cần tìm hiểu:
Để làm được điều trên, chúng ta cần có 3 bảng để lưu trữ, đó là roles, users và role_user. Chúng ta đã có model User rồi, chúng ta sẽ thêm vào cái relation cho nó:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
 
class User extends Eloquent{
    protected $table = 'users';
    public $timestamps = false;
    protected $guarded = array();
     
    public function email(){
        return $this->hasOne('Email');
    }
     
    public function roles(){
        return $this->belongsToMany('Role');
    }
}
Tương tự cho model Roles:
1
2
3
4
5
6
7
8
9
10
11
<?php
 
class Role extends Eloquent{
    protected $table = 'roles';
    public $timestamps = false;
    protected $guarded = array();
     
    public function users(){
        return $this->belongsToMany('User');
    }
}
Ở đây chúng ta sử dụng phương thức belongsToMany để mô tả relation Many To Many, vì vai trò của 2 bảng là như nhau nên ở cả 2 model đều sử dụng phương thức này mô tả liên kết đến model còn lại. Mặc đinh Laravel Framework sẽ lấy số ít của 2 table để gộp lại làm table trung gian, với ví dụ này chẳng hạn, thì table liên kết 2 table trên là user_role, tuy nhiên các bạn cũng có thể custom một table name như sau:
1
return $this->belongsToMany('Role', 'user_roles');
Để chỉ định thêm một custom foreign key chúng ta sử dụng:
1
return $this->belongsToMany('Role', 'user_roles', 'custom_user_id', 'custom_role_id');
Việc lấy dữ liệu cũng rất dễ dàng, cũng như 2 kiểu relation trên mà thôi, chúng ta chỉ cần:
1
2
3
$roles = User::find(1)->roles;
 
$users = Role::find(1)->users;

Nhận xét