Thứ Ba, 25 tháng 8, 2009

Sử dụng recursive, bindModel và unbindModel trong cakephp

Sử dụng recursive, bindModel và unbindModel sẽ giúp mọi người kiểm soát dữ liệu lấy ra trong cakephp.


1. Sử dụng Recursive


Recursive trong cakephp thể hiện mức tham chiếu quan hệ nông, sâu giữa các bảng với nhau, trong cakephp có 4 mức thể hiện tham chiếu được thể hiện qua ví dụ sau đây:


Giả sử ta có tất cả 4 bảng bao gồm: domains, groups, users và news. Và mối quan hệ giữa các bảng như sau: Một domain có rất nhiều group, trong mỗi một group lại có rất nhiều user. Một user lại có thể đăng lên rất nhiều bài viết khác nhau. Vậy là ta có thể xác định các bảng có quan hệ tham chiếu đến nhau.


Ta có thể hình dung như sau:









































table



domains



groups



users



News



domains





hasMany







groups



belongsTo





hasMany





users





belongsTo





hasMany



news







belongsTo






Giả sử ta muốn lấy dữ liệu ở bảng group theo câu lệnh $this->Group->find(‘all’). Việc sử dụng giá trị recursive sẽ cho phép ta lấy dữ liệu khác nhau.


Cú pháp sử dụng recursive trong trường hợp này là:


$this->Group->recursive = 1


























Deapth



Mô tả



-1



Lấy dữ liệu ở bảng Group, không lấy thêm bất cứ bảng nào khác



0



Lấy dữ liệu ở bảng Group và dữ liệu domain tương ứng



1



Lấy dữ liệu ở bảng Group, Domain và dữ liệu ở bảng User tương ứng



2



Lấy dữ liệu ở bảng Group, Domain, User và dữ liệu ở bảng News tương ứng




Nhìn qua bảng trên ta thấy tùy từng giá trị recursive khác nhau mà cakephp thực hiện liên kết với (inner join) thích hợp. Giả sử như ta cho recursive bằng 2, có nghĩa là ta lấy ra dữ liệu của các group, dữ liệu domain tương ứng với mỗi group đó, đồng thời là một danh sách các user nằm trong từng group, trong mỗi user đấy lại lấy ra các tin tức do các user ấy đăng. Vậy có nghĩa là sẽ có 4 bảng liên kết với nhau. Với recursive là 1 thì chỉ có 3 bảng thôi.


Như vậy là tùy tường trường hợp cụ thể mà ta có thể khai báo giá trị recursive khác nhau. Trong trường hợp ta chỉ cần lấy dữ liệu từ mỗi bảng group thì ta chỉ cần khai báo giá trị recursive là -1. Nếu muốn lấy thêm dữ liệu ở bảng domain thì khai báo recursive = 0…. Việc khai báo recursive cho từng trường hợp sẽ làm tăng tốc độ query vì ta sẽ kiểm soát được số lượng các bảng liên kết với nhau.


2. Sử dụng bindModel và unbindModel


Trong một số trường hợp, với cùng một model chúng ta sẽ phải khai báo thêm một số quan hệ hoặc bỏ bớt một số quan hệ với các bảng khác, điều này xảy ra khi:


- Bạn cần giảm bớ số lượng dữ liệu và mối quan hệ của các bảng lien quan cần lấy đến, trong khi khởi tạo ở model ta đã khai báo tất cả các quan hệ ấy rồi. (ví dụ như trong model group ở trên, ta chỉ muốn lấy dữ liệu từ 2 bảng là group và user, trong khi đó theo quan hệ ta sẽ phải join đồng thời cả 3 bảng user, group và domain. Như vậy việc truy xuất dữ liệu sẽ chậm hơn)


- Bạn muốn thay đổi cách liên kết của một model xác định để sẵp xếp hoặc lọc dữ liệu liên quan.



Khi muốn thêm một liên kết ta sẽ dùng đến bindModel và khi muốn xóa một liên kết ta sẽ sử dụng unbindModel.

Giả sử giờ ta có 2 model là user và group. Một group sẽ chứa nhiều user và mỗi user nằm trong 1 group.


Trươc tiên chúng ta sẽ khai báo 2 model




<?php
//app/models/group.php
class Group extends AppModel {
var $name = 'Group';

var $hasMany = array(
'User' => array(
'className' => 'User'
)
);
}

?>

<?php
//app/models/user.php

class User extends AppModel {
var $name = 'User';
}

?>


Giờ chúng ta sẽ xem cách hoạt động của bindModel và unbindModel qua ví dụ dưới đây. Trong groupController chúng ta sẽ lấy dữ liệu của group bằng $this->Group->find(), dữ liệu sẽ lấy luôn cả dữ liệu của user. Ví dụ minh họa dưới đây sẽ cho ta hiểu rõ hơn cách sử dùng và làm việc của bindModel và unbindModel.

function someAction() {
// Lấy dữ liệu của group, ta sẽ lấy được cả dữ liệu của user trong từng group ấy
$group = $this->Group->find('all');
echo 'Lấy theo model'
debug($group);

// Bỏ quan hệ hasMany...
$this->Group->unbindModel(
array('hasMany' => array('User'))
);

// Sử dụng lại chức năng find()
// Hiên thị group, không có user
$group = $this->Group->find('all');
echo 'Bỏ quan hệ với bảng user';
debug($group);

// Thêm quan hệ hasMany...

$this->Group->bindModel(
array('hasMany' => array(
'User' => array(
'className' => 'User'
)
)
)
);

// Sử dụng lại chức năng find()
// Hiên thị group, có user
$group = $this->Group->find('all');
echo 'Thêm quan hệ với bảng user';
debug($group);

// Bỏ quan hệ hasMany lần 2...
$this->Group->unbindModel(
array('hasMany' => array('User'))
);

// Sử dụng lại chức năng find()
// Hiên thị group, không có user
$group = $this->Group->find('all');
echo 'Bỏ quan hệ với bảng user lần 2';
debug($group);

//Chú ý: unbindModel và bindModel chỉ hiệu quả
// duy nhất trong lần lấy dữ liệu tiếp theo,
// sau lần thứ 2 sẽ lấy thông tin mặc định từ model

// Chúng ta sẽ sử dụng lại hàm find('all') sau unbindModel(),
// Dữ liệu lấy ra sẽ bao gổm cả group và user
echo 'Lấy dữ liệu mặc định';
$group = $this->Group->find('all');
debug($group);
}


Cú pháp chuẩn của unbindModel

$this->Model->unbindModel(
array('associationType' => array('associatedModelClassName'))
);


Cú pháp chuẩn của bindModel

$this->Model->bindModel(
array('associationName' => array(
'associatedModelClassName' => array(
// normal association keys go here...
)
)
)
);


Sử dụng hiệu quả recursive, bindModel và unbindModel sẽ giúp mọi người tăng tốc độ truy vấn query của cakephp vì với mỗi trường hợp lấy dữ liệu tôi đã xác định rõ các bảng cần lấy và quan hệ giữa chúng, vì vậy giảm thiều việc liên kết thừa giữa các bảng mà chúng ta không cần lấy. Chúc mọi người có một ngày vui vẻ @(^_^)@

1 nhận xét:

  1. Cảm ơn bạn. Bài viết dể hiểu và hữu ích (Y).

    Trả lờiXóa