CakePHP 实例教程: Categories Acts as Tree
Tree是CakePHP 1.2的核心Behaviors之一,可以用来轻易的实现无限极分类,并呈现树状列表。
图片来源:Tree traversa,WIKIPEDIA
基础实例
建立数据表
CREATE TABLE `categories` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`slug` VARCHAR(255) NOT NULL,
`parent_id` INT(11) DEFAULT NULL,
`lft` INT(11) DEFAULT NULL,
`rght` INT(11) DEFAULT NULL,
`link_count` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
字段说明:parent_id,lft,rght均为必要字段,parent_id是很常用的表层级关系的做法。但在这里,lft和rght才是重点。它们表示的是一个分类的左右边界。原理如下图所示
图片来源:Managing Hierarchical Data in MySQL,dev.mysql.com
建立Model
使用bake shell
$ cd app
$ cake bake
Category Model:
Categories Controller:
class CategoriesController extends AppController {
var $name = 'Categories';
}
Add Action
function add() {
if (!empty($this->data)) {
$this->Category->create();
if ($this->Category->save($this->data)) {
$this->Session->setFlash(__('The Category has been saved', true));
$this->redirect(array('action'=>'index'));
} else {
$this->Session->setFlash(__('The Category could not be saved. Please, try again.', true));
}
}
$this->set('categories', $this->Category->generatetreelist(null, null, null, '-- '));
}
add.ctp
<?php echo $form->create('Category');?>
<fieldset>
<legend><?php __('Add Category');?></legend>
<?php echo $form->input('name');?>
<?php echo $form->input('slug');?>
<?php echo $form->select('parent_id', $categories);?>
</fieldset>
<?php echo $form->end('Submit');?>
更进一步
取得层级分类
class Category extends AppModel {
var $name = 'Category';
var $actsAs = array('Tree');
function getThreadCategories() {
$this->recursive=-1;
return $this->findAllThreaded(null,null,'lft asc');
}
}
取得下属条目
当给分类下添加条目,比如Links时,基本的做法是
class Category extends AppModel {
var $name = 'Category';
var $hasMany = array(
'Links' => array('className' => 'Link',
'foreignKey' => 'category_id',
)
);
}
这样就通过Link.category_id连接了Link和对应的Category。
包含下级分类所属条目
但很多时候我们需要一个分类下的条目时,是需要包含下级分类所属条目的,此时需要添加finderQuery,并去除foreignkey:
class Category extends AppModel {
var $name = 'Category';
var $actsAs = array('Tree');
var $hasMany = array(
'Links' => array('className' => 'Link',
'foreignKey' => '',
'finderQuery' => '
SELECT
`Links`.*
FROM
`links` AS `Links`
JOIN
categories Child ON Child.id=Links.category_id
JOIN
categories Category ON Category.id={$__cakeID__$}
WHERE
(Child.lft >= Category.lft)
AND
(Child.rght <= Category.rght)
'
)
);
}
刷新条目计数
class Link extends AppModel {
var $name = 'Link';
var $belongsTo = array(
'Category' => array('className' => 'Category',
'foreignKey' => 'category_id',
)
);
function updateCounterCache ($keys = array(), $created = false) {
parent::updateCounterCache($keys, $created);
$category = $this->field('category_id');
if (!$category) {
return;
}
$conditions = array('Category.id' => $category);
$fields = array('id', 'lft', 'rght');
$recursive = -1;
$limits = $this->Category->find('first', compact('conditions', 'fields', 'recursive'));
$path = $this->Category->getPath($category, $fields);
foreach ($path as $category) {
extract ($category);
$conditions = array(
'Category.lft >=' . $Category['lft'],
'Category.rght <=' . $Category['rght'],
);
$this->Category->updateAll(
array('link_count' => intval($this->find('count', array('conditions' => $conditions)))),
array($this->Category->escapeField() => $Category['id'])
);
}
}
}
这样每当我们新建一个Link时,其所属分类及上级分类的link_count将会被自动刷新。有缺憾的是,如果我们是把一个Link从旧分类调整到新分类,旧分类的link_count不会更新。
Related posts:
- cakephp controller中设置viewVars时的陷阱 要从controller传递变量到view,需要使用set method。基本的用法是 $this->set('categories',$categories); 更顺手的写法是 $this->set(compact('categories')); 多个变量时可以这样写 $this->set('categories',$categories); $this->set('category',$category);...
- Alpha’s Categories Widget for wordpress 近来用Wordpress做一个小站,需要象Joomla一样能按Section展示多组分类。下了一个Breukie’s Categories Widget插件达成了这一功能。但当我随后升级到Wordpress 2.8的时候,这个插件却不能完好的支持。看了一下源码,原来Wordpress 2.8变更了Widgets的实现方法。于是只好自己动手,写了这个增强的Categories Widget插件:Alpha’s Categories Widget。 利用Alpha’s Categories...
- Wordpress主题berita几处修改记录 前阵子看到这篇《使用Wordpress定制企业网站》介绍的berita这个主题。界面我很喜欢,以前也确曾帮朋友用wordpress做过企业网站,于是就去下载了官方原版来用。 当然世事无完美,更没有什么主题能够完全适应各种需求。使用中发现了一些小问题,或者仅仅是不符合个人需求之处,做了一些改动,特此记录。 选择空分类作为博客页 设置面板里Blog Section Settings->Pick Category for Your Blog...
- cakephp 1.2 theme var $view = 'Theme';//themes directory var $theme = 'teline';//theme...
- cakephp 1.2 bake Ruby on rails的用户多数会在第一时间爱上它的命令行操作。cakephp也内建了一个简单的baker,可以用来执行新项目创建、配置数据库文件以及MVC的分别生成。 下载cakephp解压之后,可以在cake/console目录下找到cake.bat。建议把这个目录添加到系统PATH。 p(clipnote). windows下添加目录到系统path的操作:桌面,我的电脑,右键,属性,高级,环境变量,系统变量,PATH,编辑。 h3. 创建一个新的项目 cmd进入到你希望放置新项目的目录 cake...


27. 七, 2009 






No comments yet... Be the first to leave a reply!