Thứ Sáu, 3 tháng 7, 2009

Liên kết dữ liệu trong CakePHP

hello ngày mới...

hôm nay tôi xin giới thiếu cho những bạn đang và sắp học CakePHP về chức năng liên kết dữ liệu của Cake.

Chắc hẳn các bạn cũng đã biết việc liên kết dữ liệu gồm có 3 loại liên kết : Một - Một, Một - Nhiều,  Nhiều - Nhiều.

Công việc liên kết này khá phức tạp, làm theo cách thủ công thì ta phải liên kết các bảng dữ liệu với nhau trong cơ sở dữ liệu,điều này thì không khó lắm. Nhưng đâu đầu là ở chỗ sau đó ta phải viết hàng loạt các câu query để join các dữ liệu với nhau, nào là Join, Inner Join, Left Join, Right Join.... Riêng việc nhớ mấy câu lệnh này đã đủ tung thủ rồi chứ đừng nói đến việc nghĩ sao join cho dúng.

Nhưng giờ đây, bạn dùng Cake thì sẽ không phải ghi nhớ những câu lệnh chết tiết ấy, Cake đã làm thay cho bạn công việc đó.

Công việc của bạn bây giờ chỉ là khai báo cho Cake biết bạn định liên kết dữ liệu của bảng nào với bảng nào thôi.

Điều đó được thực hiện trong Models,cụ thể như sau :

Liên kết Một - Một (1-1) :


đầu tiên, ta tạo 2 bảng CSDL liên kết với nhau trong MySQL.

sau đó bạn tạo Model User với nội dung như sau :
<?php
class User extends AppModel {
var $name = 'User';
var $hasOne = 'Profile';
}
?>

*Chú ý : tất cả thì chắc bạn đã rõ rồi, chỉ có var $hasOne = 'Profile'; dòng chắc vẫn mù mờ, tôi giải thích như sau :

-$hasOne : câu lệnh liên kết 1-1.

-'Profile' : tên models chứa bảng liên kết đến.

Tiếp đến, trong Users_controller ta sử dụng câu lệnh :
<?php
class UsersController extends AppController {
var $name = 'Users';
function index()
{

        $this->set('user',$this->User->find());
}
?>

Như vậy là khi debug($user) ta sẽ thấy cấu trúc dữ liệu được gọi như sau :
Array
(
[User] => Array
(
[id] => 121
[name] => hello
[created] => 2007-05-01 10:31:01
)
[Profile] => Array
(
[id] => 12
[user_id] => 121
[skill] => Baking Cakes
[created] => 2007-05-01 10:31:01
)
)

Liên kết Một - Nhiều (1-m) :


Việc đầu tiên cũng vẫn là tạo bảng cơ sở dữ liệu trong MySQL.

Liên kết 1-m có vẻ đặc biệt hơn 2 liên kết còn lại. Ví dụ bạn có 2 bảng CSDL là News và Categories.

Theo logic liên kết thì, 1 category sẽ có nhiều bản ghi new, và 1 bản ghi new chỉ thuộc 1 category. Do đó liên kết sẽ là categories là 1 và news là nhiều.

Trong trường hợp bạn chọn bảng Categories để liên kết thì ta sẽ sử dụng câu lệnh 1-m : hasMany.

trong Model Category thêm câu lệnh : var $hasMany = 'New';



<?php
class Category extends AppModel
{
var $name="Category";
var $hasMany = 'New';

}
?>

Ngược lại, bạn chon bảng News để liên kết thì sẽ là m-1 : belongsTo.

trong Model New thêm câu lệnh : var $hasMany = 'Category';

<?php
class News extends AppModel
{
var $name="New";
var $hasMany = 'Category';
}
?>

giải thích về câu lệnh thì cũng như trên, tôi không cần phải nói lại nhé.

Như vậy, thì bạn sử dụng câu lệnh

$this->set('category',$this->Category->find());

trong Categories_controller, khi debug($category) bạn sẽ thấy mảng dữ liệu như sau :
Array
(
[Category] => Array
(
[id] => 11
[name] => gia dinh & be
)

[News] => Array
(
[0] => Array
(
[id] => 54
[category_id] => 11
[title] => bi hai chuyen o vien nhi
[pic] =>
[content] => bi hai chuyen o vien nhi
)

[1] => Array
(
[id] => 53
[category_id] => 11
[title] => khi nao ko nen cho be bu
[pic] =>
[content] => khi nao ko nen cho be bu
)

)

)

còn khi bạn sử dụng câu lệnh tương tự trong News_controller thì sẽ có kết quả như sau :
Array
(
[News] => Array
(
[id] => 61
[category_id] => 15
[title] => nam hoc moi
[pic] => 7b0b5e66db4e6e4e17162cb8eb7248cdimg_hello.jpg
[content] =>

* bcbcb
* truong mam non ban cong huong duong ung dung tin hoc trong giang day

[lang] => 0
)

[Category] => Array
(
[id] => 15
[name] => thong tin tuyen sinh
[lang] => 0
)

)

bạn có thể để ý câu lẹnh của Cake hiện ra ở dưới cùng, qua đó bạn có thể thấy, để có được kết quả này Cake đã phải thực hiện bao nhiêu câu query. Thử xem không sử dụng Cake thì bạn sẽ phải vật lộn với 1 mớ Select như thế nào ??

Liên kết Nhiều - Nhiều (n-m) :


Liên kết n-m nếu không có Cake thì ôi thôi, quá phức tạp. Bạn chỉ có thể liên kết n-m với nhau thông qua 1 bảng trung gian. Lấy ví dụ : tôi muốn liên kết bảng Users và bảng Groups với nhau thông qua bảng Groups_Users.

Trong bản Group_Users sẽ có Group_id và User_id.

Khi này, trong Model ta sẽ phải khai báo thêm câu lệnh để liên kết : hasAndBelongsToMany.

ở models Group :
<?php
class Group extends AppModel {
var $name = 'Group';
var $useTable = 'groups';
);
var $hasAndBelongsToMany = array(
'User' => array('className' => 'User',
'joinTable' => 'groups_users',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => true
)
);
}

?>

tại models User :
<?php
    class User extends AppModel {
        var $name = 'User';

        var $hasAndBelongsToMany = array(
                'Group' => array('className' => 'Group',
                            'joinTable' => 'groups_users',
                            'foreignKey' => 'user_id',
                            'associationForeignKey' => 'group_id',
                            'unique' => true
                )
        );
?>

không hề phải quá loằng ngoằng phức tạp tý nào, chỉ với vài dòng code trên 2 bảng Groups và Users đã liên kết n-m với nhau thông qua bảng Groups_users. Việc tiếp theo thì quá đơn giản, bạn lại find() và debug để xem kết quả liên kết thôi :


-Tại Groups_controller :  $this->set('group',$this->Group->find());


-> kết quả :



Array
(
[Group] => Array
(
[id] => 1
[name] => Toàn Quyền
)

[User] => Array
(
[0] => Array
(
[id] => 12
[acc] => tungnd
[psword] => 81379f1d1e62c9a1291708e526f3b062591de0a4
[name] => fdsf
[email] => fds
[address] => ds
[active] => 1
)

)

)

-tại Users_controller : $this->set ('user', $this->User->find());
Array
(
[User] => Array
(
[id] => 12
[acc] => tungnd
[psword] => 81379f1d1e62c9a1291708e526f3b062591de0a4
[name] => fdsf
[email] => fds
[address] => ds
[active] => 1
)

[Group] => Array
(
[0] => Array
(
[id] => 1
[name] => Toàn Quyền
)
)
)

Như vậy là tôi đã giới thiệu xong cho bạn 3 loại liên kết dữ liệu trong Cake, việc của bạn bầy giờ là hãy đọc lại, viết lại giống như tôi và biến đổi các câu lệnh find(), vận dụng linh hoạt theo ý mình.


Chúc bạn thành công........................

2 nhận xét:

  1. Theo như ví dụ của bạn về "Video", và bạn có 1 bộ phim.
    Thì theo ý mình, mình sẽ phân tích 1 bộ phim đấy là 1 new. Còn Video là 1 category lớn, bên trong có các category con như DVDrip 720p, HD, 3D....
    Như vậy thì video của bạn chuẩn DVDrip 720p thì nằm trong category DVDrip 720p chứ ko thể nhảy sang HD hay 3D được, như thế là treo đầu dê bán thịt chó rồi. :D

    1 bộ phim có thể có nhiều định dạng, nhưng mỗi định dạng đấy được tính là 1 file khác rồi chứ mình ko nghĩ là dùng file film.mp3 lại xem được hình 3D :D

    Trả lờiXóa