Khanh Hoang - Kenn
Kenn is a user experience designer and front end developer who enjoys creating beautiful and usable web and mobile experiences.
1.Nội dung :
- Trong bài viết này tôi sẽ hướng dẫn các bạn tạo menu đa cấp với CakePHP . Để tạo được menu đa cấp ta phải dùng Behavior Tree của CakePHP .Behavior Tree dựa trên thuật toán duyệt cây nhị phân . Các bạn có thể có thể tưởng tượng menu được phân thành cá cấo như cây nhị phân vậy . Ở đây , tôi chỉ hướng dẫn các bạn các làm sao dùng Behavior Tree để tạo menu đa cấp chứ không giải thích sâu vào phần thuật toán , các bạn có thể tìm tài liệu về cây nhị phân để đọc thêm .
- Các bạn có thể tham khảo Behavior Tree tại đây : http://book.cakephp.org/view/1339/Tree
- Các chức năng chính :
+ Thêm , xóa , sửa menu đa cấp
+ Hiển thị menu dạng phân cấp , sắp xếp menu theo thứ tự theo ý muốn
2. Viết ứng dụng :
a.Tạo database :
Ta tạo table tên "categories" . Lưu ý là table phải đặt tên dạng số nhiều để đảm bảo đúng qui tắc .
INSERT INTO `categories` VALUES ('1', 'My Categories', '0', '1', '0000-00-00 00:00:00', '2011-07-02 00:56:25', '1', '18');
INSERT INTO `categories` VALUES ('24', 'Joomla', '22', '0', '2011-07-02 00:40:45', '2011-07-02 00:56:25', '5', '6');
INSERT INTO `categories` VALUES ('23', 'Drupal', '22', '1', '2011-07-02 00:40:35', '2011-07-02 00:56:25', '3', '4');
INSERT INTO `categories` VALUES ('22', 'Research Object', '1', '1', '2011-07-02 00:40:21', '2011-07-02 00:56:25', '2', '7');
INSERT INTO `categories` VALUES ('20', 'Yii Framework', '17', '1', '2011-07-02 00:39:22', '2011-07-02 00:56:25', '9', '10');
INSERT INTO `categories` VALUES ('21', 'Zend Framework', '17', '0', '2011-07-02 00:39:40', '2011-07-02 00:56:25', '11', '12');
INSERT INTO `categories` VALUES ('17', 'PHP Framework', '1', '1', '2011-07-02 00:38:16', '2011-07-02 00:56:25', '8', '17');
INSERT INTO `categories` VALUES ('25', 'CakePHP', '17', '1', '2011-07-02 01:07:27', '2011-07-02 01:07:27', '15', '16');
INSERT INTO `categories` VALUES ('19', 'CodeIgniter', '17', '1', '2011-07-02 00:38:49', '2011-07-02 00:56:25', '13', '14');
b.Tạo model Category :
Tên model ở dạng số ít , nhưng table thì phải là dạng số nhiều và Controller cũng vậy .
- Model : Category
- Controller : Categories
- Table : Categories
Vào app/models/ tạo file category.php
<?php
class Category extends AppModel {
var $name = #DD0000">'Category';
var $displayField = #DD0000">'name';
var $actsAs = array(#DD0000">'Tree'); #FF8000">// Thiet lap quan he
var $validate = array(
#DD0000">'name' => array(
#DD0000">'notempty' => array(
#DD0000">'rule' => array(#DD0000">'notempty'),
#FF8000">//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
#DD0000">'published' => array(
#DD0000">'numeric' => array(
#DD0000">'rule' => array(#DD0000">'numeric'),
#FF8000">//'message' => 'Your custom message here',
//'allowEmpty' => false,
//'required' => false,
//'last' => false, // Stop validation after this rule
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
)
);
var $belongsTo = array(
#DD0000">'ParentCat' => array(
#DD0000">'className' => #DD0000">'Category',
#DD0000">'foreignKey' => #DD0000">'parent_id'
)
);
}
?>
c. Tạo Controller Categories :
Vào app/controllers/ tạo file categories_controller.php với nội dung sau
<?php
class CategoriesController extends AppController {
var $name = #DD0000">'Categories';
var $components = array(#DD0000">'Session');
function index() {
$this->set(#DD0000">'Categories', $this->Category->find(#DD0000">"all"));
$this->set(#DD0000">'list_cat',$this->_find_list());
}
function add() {
if (!empty($this->data)) {
$this->Category->create();
if ($this->Category->save($this->data)) {
$this->Session->setFlash(__(#DD0000">'The product category has been saved', true));
$this->redirect(array(#DD0000">'action' => #DD0000">'index'));
} else {
$this->Session->setFlash(__(#DD0000">'The product category could not be saved. Please, try again.', true));
}
}
$this->set(#DD0000">'list_cat',$this->_find_list());
}
function edit($id){
if (!$id && empty($this->data)) {
$this->Session->setFlash(#DD0000">'Invalid Category');
$this->redirect(array(#DD0000">'action'=>#DD0000">'index'));
}
if (empty($this->data)) {
$this->data = $this->Category->read(null, $id);
}
else {
if($this->Category->save($this->data)) {
$this->Session->setFlash(#DD0000">'Category is Updated!', true);
$this->redirect(array(#DD0000">'action'=>#DD0000">'index'), null, true);
}
}
$this->set(#DD0000">'list_cat',$this->_find_list());
}
function delete($id){
$this->Category->removeFromTree($id,true);
$this->redirect(array(#DD0000">'action'=>#DD0000">'index'), null, true);
}
function movedown($name=null,$delta=null){
$cat = $this->Category->findByName($name);
if (empty($cat)) {
$this->Session->setFlash(#DD0000">'There is no category named ' . $name);
$this->redirect(array(#DD0000">'action' => #DD0000">'index'), null, true);
}
$this->Category->id = $cat[#DD0000">'Category'][#DD0000">'id'];
if($delta>0){
$this->Category->moveDown($this->Category->id, abs($delta));
}else{
$this->Session->setFlash(#DD0000">'Please provide the number of positions the field should be moved down.');
}
$this->redirect(array(#DD0000">'action' => #DD0000">'index'));
}
function moveup($name = null, $delta = null){
$cat = $this->Category->findByName($name);
if (empty($cat)) {
$this->Session->setFlash(#DD0000">'There is no category named ' . $name);
$this->redirect(array(#DD0000">'action' => #DD0000">'index'), null, true);
}
$this->Category->id = $cat[#DD0000">'Category'][#DD0000">'id'];
if ($delta > 0) {
$this->Category->moveUp($this->Category->id, abs($delta));
} else {
$this->Session->setFlash(#DD0000">'Please provide a number of positions the category should be moved up.');
}
$this->redirect(array(#DD0000">'action' => #DD0000">'index'), null, true);
}
function _find_list() {
return $this->Category->generateTreeList();
}
}
?>
c. Tạo các file view cho từng function trong Controller Categories
- Vào app/views/ tạo thư mục categories
- Vào app/views/categories/ tạo các file sau :
File index.ctp cho function index()
<!--Show menu tree-->
<div class="productCategories left" style="float: left;">
<h2>Menu</h2>
<ul>
<?php
foreach($list_cat as $item){
echo #DD0000">"<li>".$item.#DD0000">"</li>";
}
?>
</ul>
</div>
<!-- Modify menu tree-->
<div class="productCategories index">
<h2>Modify | <?php echo $this->Html->link(#DD0000">"Add new",array(#DD0000">"controller"=>#DD0000">"categories",#DD0000">"action"=>#DD0000">"add"));?></h2>
<h2><?php __(#DD0000">'Categories');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th>ID</th>
<th>Name</th>
<th>Parent ID</th>
<th>Published</th>
<th class="actions"><?php __(#DD0000">'Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($Categories as $Category){
$class = null;
if ($i++ % 2 == 0) {
$class = #DD0000">' class="altrow"';
}
?>
<tr<?php echo $class;?>>
<td><?php echo $Category[#DD0000">'Category'][#DD0000">'id']; ?> </td>
<td><?php echo $Category[#DD0000">'Category'][#DD0000">'name']; ?> </td>
<td><?php echo $Category[#DD0000">'ParentCat'][#DD0000">'name']; ?> </td>
<td><?php echo $Category[#DD0000">'Category'][#DD0000">'published']; ?> </td>
<td class="actions">
<?php echo $this->Html->link(__(#DD0000">'Up', true), array(#DD0000">'action' => #DD0000">'moveup/'.$Category[#DD0000">'Category'][#DD0000">'name'], $Category[#DD0000">'Category'][#DD0000">'id'])); ?>
<?php echo $this->Html->link(__(#DD0000">'Down', true), array(#DD0000">'action' => #DD0000">'movedown/'.$Category[#DD0000">'Category'][#DD0000">'name'], $Category[#DD0000">'Category'][#DD0000">'id'])); ?>
</td>
<td class="actions">
<?php echo $this->Html->link(__(#DD0000">'Edit', true), array(#DD0000">'action' => #DD0000">'edit', $Category[#DD0000">'Category'][#DD0000">'id'])); ?>
<?php echo $this->Html->link(__(#DD0000">'Delete', true), array(#DD0000">'action' => #DD0000">'delete', $Category[#DD0000">'Category'][#DD0000">'id']), null, sprintf(__(#DD0000">'Are you sure you want to delete # %s?', true), $Category[#DD0000">'Category'][#DD0000">'id'])); ?>
</td>
</tr>
<?php } ?>
</table>
</div>
File add.ctp cho function add()
<div class="productCategories form">
<?php echo $this->Form->create(#DD0000">'Category');?>
<fieldset>
<legend><?php __(#DD0000">'Add Category'); ?></legend>
<?php
echo $this->Form->input(#DD0000">'name');
echo $this->Form->input(#DD0000">'parent_id',array(#DD0000">'type'=>#DD0000">'select',#DD0000">'options'=>$list_cat,#DD0000">'empty'=>#DD0000">'--Choose parent--'));
echo $this->Form->input(#DD0000">'published');
?>
</fieldset>
<?php echo $this->Form->end(__(#DD0000">'Submit', true));?>
</div>
File edit.ctp cho function edit()
<div class="productCategories form">
<?php echo $this->Form->create(#DD0000">'Category');?>
<fieldset>
<legend><?php __(#DD0000">'Add Category'); ?></legend>
<?php
echo $this->Form->input(#DD0000">'name');
echo $this->Form->input(#DD0000">'parent_id',array(#DD0000">'type'=>#DD0000">'select',#DD0000">'options'=>$list_cat,#DD0000">'empty'=>#DD0000">'--Choose parent--'));
echo $this->Form->input(#DD0000">'published');
?>
</fieldset>
<?php echo $this->Form->end(__(#DD0000">'Submit', true));?>
</div>
- Đối với hàm delete, moveUp, moveDown không có file view.
3.Chạy thử ứng dụng :
- Trang chủ : http://localhost/cakephp/categories/
- Trang add : http://localhost/cakephp/categories/add
- Trang edit : http://localhost/cakephp/categories/edit/1