SQL:
CREATE TABLE categories (
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INTEGER(10) DEFAULT NULL,
lft INTEGER(10) DEFAULT NULL,
rght INTEGER(10) DEFAULT NULL,
name VARCHAR(255) DEFAULT '',
PRIMARY KEY (id)
);
Now insert some record:
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(1, 'Tutorials', NULL, 1, 8);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(2, 'PHP', 1, 2, 5);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(3, 'MySQL', 1, 6, 7);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(4, 'CakePHP', 2, 3, 4);
Now I'll create a model for this category.
1. Create a new file.
2. Copy-paste the following code:
<?php
class Category extends AppModel {
var $name = 'Category';
var $actsAs = array('Tree');
}
?>
3. Save the files as app/models/category.php.
Note:
The variable $actsAs tells Cake to attach 'Tree' behavior to this model, i.e., Cake will generate a Tree data structure for category model. I think it is also a good time to introduce you with another fascinating feature of CakePHP - 'Behaviors'. CakePHP has built-in behaviors, like - behaviors for tree structures, translated content, access control list interaction etc., which you can attach with any model. As you might know - 'add', 'edit', 'delete' options for these type of data structures need special care. Cake takes care of it once you have specified the applicable 'behavior' in the model. Behaviors are attached with models using $actsAs variable. In this case, I have specified $actsAs = array('Tree'). This will enforce 'Tree' behavior on Category model. Simple.
To learn more about 'Behaviors', please refer to CakePHP online book.
Step:
1. Create a new file.
2. Copy-paste the following code.
<?php
class CategoriesController extends AppController {
var $name = 'Categories';
function index() {
$categories = $this->Category->generatetreelist(null, null, null, ' ');
$this->set(compact('categories'));
}
}
?>
3. Save that file as categories_controller.php under 'app/controllers' folder.
Note: generatetreelist() method generates a tree-type views for our Categories. There are lots of options you can use with this method. For a complete guidelines on options for this method, please refer to CakePHP book.
compact(); function is used to pass variables to your views in CakePHP. Compact() method detects the variables having the same name (in this case 'categories') in your Controller and splits them as an array() of $key => value pairs. Now $this->set() is used to set those values for using them in your view file.
Now I'll create a view for our index() function.
file: '/app/views/categories/index.php'
<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
foreach($categories as $key=>$value){
echo "<li>$value</li>";
}
echo "</ul>";
?>
Now point your browser to:
http://caketest.local/categories
And you should see following structure:
> Tutorials
> PHP
> CakePHP
> MySQL
To Add a new category to the list:
1. Open categories_controller.php (found under '/app/controllers')
2. Copy-paste the following function:
function add() {
if (!empty($this -> data) ) {
$this->Category->save($this -> data);
$this->Session->setFlash('A new category has been added');
$this->redirect(array('action' => 'index'));
} else {
$parents[0] = "[Top]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories) {
foreach ($categories as $key=>$value)
$parents[$key] = $value;
}
$this->set(compact('parents'));
}
}
3. Save this file.
Now we need to create a view file for this add() method (to display the add category form).
1. Create a new file.
2. Copy-paste the following code:
<h1>Add a new category</h1>
<?php
echo $form->create('Category');
echo $form->input('parent_id',array('label'=>'Parent'));
echo $form->input('name',array('label'=>'Name'));
echo $form->end('Add');
?>
3. Save the file as '/app/views/categories/add.ctp'
Now point your browser to this location:
http://caketest.local/categories/add
You should be able to add a new category.
EDIT Category
To edit category, I'll specify a controller action. To do so:
1. Open categories_controller.php (found under '/app/controllers').
2. Copy-paste the following function:
function edit($id=null) {
if (!empty($this->data)) {
if($this->Category->save($this->data)==false)
$this->Session->setFlash('Error saving Node.');
$this->redirect(array('action'=>'index'));
} else {
if($id==null) die("No ID received");
$this->data = $this->Category->read(null, $id);
$parents[0] = "[ Top ]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories)
foreach ($categories as $key=>$value)
$parents[$key] = $value;
$this->set(compact('parents'));
}
}
3. Save that function.
Now, I'll write the view file (the form to edit a category). To do so:
1. Create a new file.
2. Copy paste the following code:
<?php
echo $html->link('Back',array('action'=>'index'));
echo $form->create('Category');
echo $form->hidden('id');
echo $form->input('name');
echo $form->input('parent_id', array('selected'=>$this->data['Category']['parent_id']));
echo $form->end('Update');
?>
3. Now save the file as '/app/views/categories/edit.ctp'.
Hold on!
There is one more thing we should do. We need to show the link to edit record. To do show:
1. Open '/app/views/categories/index.ctp' file.
2. Replace the existing code with this one:
<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
foreach($categories as $key=>$value){
$edit = $html->link("Edit", array('action'=>'edit', $key));
echo "<li>$value [$edit]</li>";
}
echo "</ul>";
?>
3. Now save the file.
Now point your browser to:
http://caketest.local/categories/
You should be able to see the 'Edit' option against each category name.
Delete Category
CakePHP Format:
removeFromTree($id=null, $delete=false)
Using this method will either delete [to delete, set ($delete=true)] or move a node but retain its sub-tree, which will be re-parented one level higher.
Steps:
1. Open '/app/controllers/categories_controller.php'
2. Copy paste the following code:
function delete($id=null) {
if($id==null)
die("No ID received");
$this->Category->id=$id;
if($this->Category->removeFromTree($id,true)==false)
$this->Session->setFlash('The Category could not be deleted.');
$this->Session->setFlash('Category has been deleted.');
$this->redirect(array('action'=>'index'));
}
3. Now save that file.
Next, I'll display the option to 'delete' a category.
Step:
1. Open '/app/views/categories/index.ctp
2. Replace the existing code with this one:
<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
foreach($categories as $key=>$value){
$edit = $html->link("Edit", array('action'=>'edit', $key));
$delete = $html->link("Delete", array('action'=>'delete', $key));
echo "<li>$value [$edit] [$delete]</li>";
}
echo "</ul>";
?>
3. Save the file.
Done
Point your browser to:
http://caketest.local/categories
Here is a screenshot of what you should see:
[ACKNOWLEDGEMENT]
The code above is mostly based on
Bram Borggreve's beautiful website - Tree Behavior
I express my sincere gratitude to Bram for his wonderful contribution.
I express my sincere gratitude to Bram for his wonderful contribution.
Further, to learn more about 'Tree' behavior, please visit: CakePHP Book.
Here is the COMPLETE script files:
1. categories_controller.php ('to be saved under '/app/controllers')
<?php
class CategoriesController extends AppController {
var $name = 'Categories';
function index() {
$categories = $this->Category->generatetreelist(null, null, null, ' ');
// debug ($this->data); die;
$this->set(compact('categories'));
}
function add() {
if (!empty($this -> data) ) {
$this->Category->save($this -> data);
$this->Session->setFlash('A new category has been added');
$this->redirect(array('action' => 'index'));
} else {
$parents[0] = "[ Top ]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories) {
foreach ($categories as $key=>$value)
$parents[$key] = $value;
}
$this->set(compact('parents'));
}
}
function edit($id=null) {
if (!empty($this->data)) {
if($this->Category->save($this->data)==false)
$this->Session->setFlash('Error saving Category.');
$this->redirect(array('action'=>'index'));
} else {
if($id==null) die("No ID received");
$this->data = $this->Category->read(null, $id);
$parents[0] = "[ Top ]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories)
foreach ($categories as $key=>$value)
$parents[$key] = $value;
$this->set(compact('parents'));
}
}
function delete($id=null) {
if($id==null)
die("No ID received");
$this->Category->id=$id;
if($this->Category->removeFromTree($id,true)==false)
$this->Session->setFlash('The Category could not be deleted.');
$this->Session->setFlash('Category has been deleted.');
$this->redirect(array('action'=>'index'));
}
}
?>
Here is the COMPLETE script files:
1. categories_controller.php ('to be saved under '/app/controllers')
<?php
class CategoriesController extends AppController {
var $name = 'Categories';
function index() {
$categories = $this->Category->generatetreelist(null, null, null, ' ');
// debug ($this->data); die;
$this->set(compact('categories'));
}
function add() {
if (!empty($this -> data) ) {
$this->Category->save($this -> data);
$this->Session->setFlash('A new category has been added');
$this->redirect(array('action' => 'index'));
} else {
$parents[0] = "[ Top ]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories) {
foreach ($categories as $key=>$value)
$parents[$key] = $value;
}
$this->set(compact('parents'));
}
}
function edit($id=null) {
if (!empty($this->data)) {
if($this->Category->save($this->data)==false)
$this->Session->setFlash('Error saving Category.');
$this->redirect(array('action'=>'index'));
} else {
if($id==null) die("No ID received");
$this->data = $this->Category->read(null, $id);
$parents[0] = "[ Top ]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories)
foreach ($categories as $key=>$value)
$parents[$key] = $value;
$this->set(compact('parents'));
}
}
function delete($id=null) {
if($id==null)
die("No ID received");
$this->Category->id=$id;
if($this->Category->removeFromTree($id,true)==false)
$this->Session->setFlash('The Category could not be deleted.');
$this->Session->setFlash('Category has been deleted.');
$this->redirect(array('action'=>'index'));
}
}
?>
2. Category Model (file: '/app/models/category.php')
<?php
class Category extends AppModel {
var $name = 'Category';
var $actsAs = array('Tree');
}
?>
3. Views for Category Files
(a)File: '/app/views/categories/index.php'
<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
foreach($categories as $key=>$value){
$edit = $html->link("Edit", array('action'=>'edit', $key));
$delete = $html->link("Delete", array('action'=>'delete', $key));
echo "<li>$value [$edit] [$delete]</li>";
}
echo "</ul>";
?>
(b) File: '/app/views/categories/add.php'
<h1>Add a new category</h1>
<?php
echo $form->create('Category');
echo $form->input('parent_id',array('label'=>'Parent'));
echo $form->input('name',array('label'=>'Name'));
echo $form->end('Add');
?>
(c) File: 'app/views/categories/edit.php'
<h1>Add a new category</h1>
<?php
echo $form->create('Category');
echo $form->input('parent_id',array('label'=>'Parent'));
echo $form->input('name',array('label'=>'Name'));
echo $form->end('Add');
?>
Thanks for reading the entry.
16 comments:
Hi Nilz,
I say you uses parts of my tutorial, thanks for the acknowledgement! :)
Regards, Bram
Thanks for your visit.
Your tutorial was really great and original. My tutorial is mostly based on your work. I have merely changed few variable names. Thanks again for your good words.
That helped ! Thank you for that great example ;)
Thanks.
Really Helpful stuff...
Thanks 4 brief and well organized Description.
Thanks Vyas.
Its really helpful, and learned a lot
Really fine and I learned a lot.
Thanks
Thanks...
I have read your blog and i got a very useful and knowledgeable information from your blog.its really a very nice article.You have done a great job .
Thank you so much
Cake PHP developmentfor sharing.
Thanks @USEO!
Several years have passed, and this tutorial is still useful. Thanks !
Several years have passed, and this tutorial is still useful. Thanks !
Several years have passed, and this tutorial is still useful. Thanks !
Several years have passed, and this tutorial is still useful. Thanks !
Am very grateful for this post. as old has it is its still applicable and relevance.
is there a way to show the tree in the form of organizational structure. that is
A
B C D
E F G H I J K L M
Post a Comment