Chủ Nhật, 30 tháng 8, 2009

Note Config Apache

Cấu hình cho Apache hiển thị file Gzip .

- Cài module mod_defalte.so vào thư mục .../apache2.2/modules

- Sửa file .../apache2/conf/httpd.conf enable mod_deflate.so
LoadModule deflate_module modules/mod_deflate.so

- Add MultiViews to Options:
Options Indexes FollowSymLinks MultiViews

- Uncomment AddEncoding:
AddEncoding x-compress .Z
AddEncoding x-gzip .gz .tgz
- Comment AddType:
#AddType application/x-compress .Z
#AddType application/x-gzip .gz .tgz

- Để hiển thị file Gzip dưới dạng xml thêm dòng :
AddType text/xml .gz .tgz

- Khởi động lại Apache:
.../httpd restart

Thứ Ba, 25 tháng 8, 2009

So sánh cách lấy dữ liệu tự động và lấy theo query trong cakephp

I. So sánh


Trong cakephp, có 2 cách lấy dữ liệu chính là lấy dự liệu tự động thông qua các hàm viết sẵn của cakephp và lấy dữ liệu từ câu lệnh query trực tiếp.


Ưu nhược điểm của 2 phương pháp trên:


1. Lấy dữ liệu tự động


a) Ưu điểm


- Lấy dữ liệu từ các bảng sẽ được thực hiện tự động thông qua khai báo quan hệ ở model


- Việc thêm quan hệ hoặc thay đổi quan hệ giữa các bảng sẽ được thực hiện ở model, vì vậy khi quan hệ với bảng khác hoặc thay đổi dữ liệu chỉ cần thay đổi quan hệ ở model.


- Dễ dàng hơn trong việc phân trang, phân trang tìm kiếm.


- Dữ liệu lấy ra đã được đưa theo cấu trúc mảng hình cây hợp lý, làm cho việc hiển thị dữ liệu trở lên đơn giản và dễ dàng hơn.


b) Nhược điểm


- Việc lấy dữ liệu sẽ trở lên vô cùng nhiều và chậm do lấy dữ liệu từ tẩt cả các bảng quan hệ nếu không sử dụng hợp lý recursive và bindModel (cách dùng sẽ có ở dưới).


c) Định dạng dữ liệu lấy ra


Dữ liệu lấy ra sẽ được hiển thị theo nhiều định dang, tùy theo từng mối quan hệ là một – một, một nhiều hay nhiều nhiều.


- Với quan hệ một - một:



Array

(

    [User] => Array

        (

            [id] => 121

            [name] => Gwoo the Kungwoo

            [created] => 2007-05-01 10:31:01

        )

    [Profile] => Array

        (

            [id] => 12

            [user_id] => 121

            [skill] => Baking Cakes

            [created] => 2007-05-01 10:31:01

        )

)


- Với quan hệ một nhiều:



Array

(  

    [User] => Array

        (

            [id] => 121

            [name] => Gwoo the Kungwoo

            [created] => 2007-05-01 10:31:01

        )

    [Comment] => Array

        (

            [0] => Array

                (

                    [id] => 123

                    [user_id] => 121

                    [title] => On Gwoo the Kungwoo

                    [body] => The Kungwooness is not so Gwooish

                    [created] => 2006-05-01 10:31:01

                )

            [1] => Array

                (

                    [id] => 124

                    [user_id] => 121

                    [title] => More on Gwoo

                    [body] => But what of the ‘Nut?

                    [created] => 2006-05-01 10:41:01

                )

        )

)


- Quan hệ nhiều – một



Array

(

   [Profile] => Array

        (

            [id] => 12

            [user_id] => 121

            [skill] => Baking Cakes

            [created] => 2007-05-01 10:31:01

        )    

    [User] => Array

        (

            [id] => 121

            [name] => Gwoo the Kungwoo

            [created] => 2007-05-01 10:31:01

        )

)

- Quan hệ nhiều nhiều
Array

(  

    [Recipe] => Array

        (

            [id] => 2745

            [name] => Chocolate Frosted Sugar Bombs

            [created] => 2007-05-01 10:31:01

            [user_id] => 2346

        )

    [Tag] => Array

        (

            [0] => Array

                (

                    [id] => 123

                    [name] => Breakfast

                )

           [1] => Array

                (

                    [id] => 124

                    [name] => Dessert

                )

           [2] => Array

                (

                    [id] => 125

                    [name] => Heart Disease

                )

        )

)


2. Lấy dữ liệu từ câu lệnh query


a) Ưu điểm


- Việc lấy dữ liệu sẽ không còn phụ thuộc vào quan hệ ở model, mà chỉ phụ thuộc vào quan hệ khi khai báo ở câu query


- Việc lấy dữ liệu sẽ thực hiện nhanh hơn, liên kết giữa các bảng sẽ rõ ràng hơn dựa vào câu lệnh liên kết ở query.


b) Nhược điểm


- Khi thay đổi quan hệ giữa các bảng, hoặc thêm quan hệ với một bảng mới, phải sửa lại câu query.


- Việc phân trang sẽ trở nên khó khăn phức tạp hơn


- Dữ liệu lấy ra dưới dạng mảng, nhưng chưa được sắp xếp lại theo cấu trúc.


- Khi sử dụng câu lệnh query, ta phải hiểu rất rõ quan hệ và sử dụng thành thao các lệnh trong query


c) Định dạng dữ liệu lấy ra


Khi lấy dữ liệu thông qua câu lệnh query, thì với tất cả các quan hệ dữ liệu dữ liệu lấy ra từ câu lệnh query đểu có định dạng như sau:


Array


(



   [0] => Array
      (

[Category] => Array


(


[id] => 1


[name] => Thông tin thị trường


[alias] => tin_tuc


[parent_id] =>


[root_path] =>


[level] => 0


[order] =>


[lang] =>


[represent] =>


[is_hyperlink] => 0


[active] => 0


[layout] => 0


[created] => 0000-00-00 00:00:00


)



[NewsCategory] => Array


(


[id] => 16


[news_id] => 4


[category_id] => 1


)



)



[1] => Array


(


[Category] => Array


(


[id] => 2


[name] => Phân tích thị trường


[alias] =>


[parent_id] =>


[root_path] =>


[level] => 0


[order] =>


[lang] =>


[represent] =>


[is_hyperlink] => 0


[active] => 0


[layout] => 0


[created] => 0000-00-00 00:00:00


)



[NewsCategory] => Array


(


[id] => 17


[news_id] => 4


[category_id] => 2


)



)


...



)


3. So sánh tốc độ


Thực tế, cách sử dụng query và cách sử dụng lấy dữ liệu tự động thông qua các hàm find, findAll… sẽ không khác nhau là mấy hay nói đúng hơn là không khác gì nhau khi ta xác định rõ ràng recursive trong từng trường hơp cụ thể, kết hợp với sự dụng bindModel và unbindModel để xác định số lượng các bảng tham gia inner join.


II. Tối ưu dữ liệu theo cách lấy tự động


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. (Cách sử dụng bindModel va unbindMode sẽ được bàn sau)

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ẻ @(^_^)@

Thứ Hai, 10 tháng 8, 2009

Sử dụng plugin trong cakephp 1.2!

Hello cả nhà!

Hôm nay tôi xin giới thiệu với mọi người về cách sử dụng plugin trong cakephp. Như mọi người đều biết, cakephp là một framework hỗ trợ lập trình php một cách nhanh chóng và hiệu quả nhất. Sử dụng cakephp sẽ làm tăng tốc độ phát triển các dự án lên nhiều lần. Trong quá trình phát triển dự án, việc sử dụng đi sử dụng lại các đoạn code viết sẵn là đỉều tất yếu. Vậy sử dụng lại code như thế nào cho hiệu quả cũng là một bài toán đáng để quan tâm. Nếu như mọi người cứ copy nguyên code các dự án đã có rồi phát triển nên, sẽ làm cho code ngày càng nhiều khó quản lý và tái sử dụng ở các lần sau. Với cakephp, việc tái sử dụng code sẽ trở nên đơn giản hơn thông qua sử dụng tiện ích plugin. Các module chức năng sẽ được tách riêng ra thành các plugin, và khi sử dụng module chức năng nào, ta chỉ việc đưa plugin đó vào trong cakephp mà thôi. Việc sử dụng plugin sẽ làm cho các chức năng trở nên rõ ràng, tách biệt và dễ quản lý, maintain cũng như phát triên nên.

Việc tạo một plugin trong cakephp vô cùng đơn giản và dễ hiểu. Để tạo ra một plug, chúng ta sẽ đưa vào trong thư mục app/plugins. Ví dụ sau đây chúng ta sẽ tạo ra một plugin tin tức với các chức năng thêm sửa xóa. Đâu tiên sẽ là tạo ra CSDL tên là plugin trong đó có bảng news:

CREATE TABLE IF NOT EXISTS `news` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`title` varchar(255) DEFAULT NULL,
`description` text,
`content` text,
`created` datetime DEFAULT NULL,
`user_id` int(4) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

CREATE TABLE IF NOT EXISTS `users` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Việc cấu hình database kết nối đến CSDL mới tạo tôi sẽ để mọi người tự làm nhé (Đây là công việc cơ bản mà ^_^ ). Tiếp theo ta sẽ tạo ra một plugin tintuc bằng cách thêm một thư mục tintuc như sau : app/plugins/tintuc . Cấu trúc bên trong thư mục tin tức sẽ giống hệt như là cấu trúc bên trong thư mục app. Ta sẽ có một thư thư mục cơ bản cần thiết như sau:

+ Thư mục controller như sau: app/plugins/tintuc/controllers.

+ Thư mục view như sau:  app/plugins/tintuc/view

+ Thư mục models như sau:  app/plugins/tintuc/models

+ Thư mục layout như sau:  app/plugins/tintuc/layouts

+ Thư mục helpers như sau:  app/plugins/tintuc/view/helpers

+ Thư mục components như sau:  app/plugins/tintuc/controllers/components

+ Tệp tin TintucAppController: app/plugins/tintuc/tintuc_app_controller.php

+ Tệp tin TintucAppModel: app/plugins/tintuc/tintuc_app_model.php

+ .......................................

Như đã thấy ở trên, cấu trúc các thư mục trong plugin sẽ tương tự như cấu trúc thư mục như trong phần app. Riêng 2 file tintuc_app_controller.php và tintuc_app_model.php sẽ có nội dung như sau:
//app/plugins/tintuc/tintuc_app_controller.php

<?php
class TinTucAppController extends AppController {

}
?>

//app/plugins/tintuc/tintuc_app_model.php

<?php
class TintucAppModel extends AppModel {

}
?>

Tiếp theo ta sẽ khai báo một news_controllers theo app/plugins/tintuc/controllers/news_controller.php
<?php
class NewsController extends TintucAppController
{

var $name = 'News';
var $uses = array('Tintuc.News');
var $helpers = array('Html', 'Form', 'Javascript');

function index($param=null)
{
$this->News->recursive = 0;
$this->paginate = array('limit' => 15, 'page' => 1, 'order' => array('News.created' => 'desc'));
$this->set ('news', $this->paginate ('News'));
}

function add()
{
$this->layout = 'homepage';
if(! empty ($this->data))
{
$this->News->create ();
if($this->News->save ($this->data))
{
$this->Session->setFlash (__ ('The News has been saved', true));
$this->redirect ('/tintuc/news/index');
}else
{
$this->Session->setFlash (__ ('The News could not be saved. Please, try again.', true));
}
}
}

function edit($id = null)
{
if(! $id && empty ($this->data))
{
$this->Session->setFlash (__ ('Invalid News', true));
$this->redirect (array('action' => 'index'));
}
$news = $this->News->read (null, $id);
if(! empty ($this->data))
{
if($this->News->save ($this->data))
{
$this->Session->setFlash (__ ('The News has been saved', true));
$this->redirect ('/tintuc/news/index');
}else
{
$this->Session->setFlash (__ ('The News could not be saved. Please, try again.', true));
}
}

if(empty ($this->data))
{
$this->data = $news;
}
}

function delete($id = null)
{
if(! $id)
{
$this->Session->setFlash (__ ('Invalid id for News', true));
$this->redirect ('/tintuc/news/index');
}
$del_news = $this->News->findById ($id);
if($this->News->del ($id))
{
$this->Session->setFlash (__ ('News deleted', true));
$this->redirect ('/tintuc/news/index');
}
}

}
?>

Khai báo tiếp một file model news.php theo đường dẫn app/plugins/tintuc/models/news.php
<?php
class News extends TintucAppModel {
var $name = 'News';
var $belongsTo = array('User');
}
?>

Vậy là đã xong controller và model. Giờ tôi sẽ tạo ra 3 view là index, add và edit
//app/plugins/tintuc/views/news/add.ctp

<?php
echo $form->create('News', array('url' => '/tintuc/news/add'));
echo $form->input('title');
echo $form->input('description');
echo $form->input('created');
echo $form->input('content');
echo $form->end('Submit');
?>

//app/plugins/tintuc/views/news/edit.ctp

<?php
echo $form->create('News');
echo $form->hidden('id');
echo $form->input('title');
echo $form->input('description');
echo $form->input('created');
echo $form->input('content');
echo $form->end('Submit');
?>

//app/plugins/tintuc/views/news/index.ctp

<h2>Index</h2>

<table>
<tr>
<th>Title</th>
<th>User</th>
<th>Created</th>
<th>Action</th>
</tr>
<?php
foreach ($news as $n)
{
?>
<tr>
<td><?=$n['News']['title']?></td>
<td><?=$n['User']['name']?></td>
<td><?=$n['News']['created']?></td>
<td>
<?=$html->link('Edit', '/tintuc/news/edit/'.$n['News']['id']);?>
<?=$html->link('Delete', '/tintuc/news/delete/'.$n['News']['id'], null, sprintf(__('Are you sure you want to delete # %s?', true), $n['News']['id']));?>
</td>
</tr>
<?php
}
?>
</table>

<?=$html->link('Add', '/tintuc/news/add')?>

Tôi đã vừa hoàn thành một plugin cơ bản trong cakephp. Bây giờ tôi sẽ lấy dữ liệu từ plugin thông qua một test_controller như sau:
//app/controllers/tests_controllers.php

<?php
class TestController extends AppController {

var $name = 'Test';
var $uses = array('Tintuc.News);

function index()
{
debug($this->News->find('all'));
die();
}
}
?>

Trong plugin ta còn có thể tạo ra các components, helpers, layouts riêng cho mình. Các file này sẽ nằm ở các thư mục tương ứng trong plugins. Việc tao ra các class components, helpers, layout tương tự như thêm components, helpers hoặc layout bình thường.  Sử dụng các components, helpers, layouts trong controller như sau:

var $components = array('Tintuc.Comp');

Như vậy là ta chỉ thêm tên các plugin phía trước các components và helper mà thôi, riêng với layout tao khai báo như bình thương, vì nó sẽ mặc định là chồng đề lên thư mục app/views/layouts.
var $layout = 'temp_layout';

Việc chỉ định sử dụng các file javascript, css và ảnh sẽ được lưu vào trong các thư mục tương ứng là tintuc/vendors/js, tintuc/vendors/css and tintuc/vendors/img và sẽ được gọi như sau:

<?php echo $html->image('/tintuc/img/my_image.png'); ?>

<?php echo $html->css('/tintuc/css/my_css'); ?>

<?php echo $javascript->link('/tintuc/js/do_cool_stuff'); ?>

Tôi đã trình bày mọi thứ cơ bản liên quan đến plugin với mọi người rồi, giờ mọi người hãy tự trải nghiêm nhé. Chúc cả nhà vui vẻ @(^_^)@.