需求分析:
1.商品分类管理无限级分类
2.添加商品时,要指定商品属于主分类和多个扩展分类
3.商品列表根据分类搜索商品
1) 搜索一个分类下商品时,这个分类所有子分类下的商品也应该被搜索出来
2)搜索时要考虑商品的主分类和扩展分类
递归一 打印树形结构
建表:
商品分类表
递归二 找一个分类所有的子分类
create table p39_category(
id mediumint unsigned not null auto_increment comment 'Id',
cat_name varchar(30) not null comment '分类名称',
parent_id mediumint unsigned not null default '0'comment '上级分类的Id,0:顶级分类 ',
primary key (id)
)engine=InnoDB default charset=utf8 comment '分类 ';
2做模型
找子分类id递归
public function getChildren($catId){
//取出所有的分类
$data=$this->select();
////递归从所有的分类中挑出子分类的ID
return $this->_getChildren($data,$cateId,TRUE);
}
//递归从数据中找子分类
private function _getChildren($data,$catId,$isClear=FALSE){
static $_ret=array();//保存找到的子分类的ID
if($isClear){
$_ret=array();
}
foreach ($data as $k=>$v)
{
if($v['parent_id']==$cateId){
$_ret[]=$v['id'];
////再找这个$v的子分类
$this->_getChildren($data, $v['id']);
}
return $_ret;
}
}
递归:重新排序打印树形数据
public function getTree(){
$data=$this->select();
return $this->_getTree($data);
}
private function _getTree($data,$parent_id=0,$level=0){
static $_ret=array();
foreach ($data as $k=>$v){
if($v['parent_id']==$parent_id){
$v['level']=$level;
$_ret[]=$v;
//找子分类
$this->_getTree($data,$v['id'],$level+1);
}
}
return $_ret;
}
第二步 控制器中做lst方法
namespace Admin\Controller;
use Think\Controller;
class CategoryController extends Controller {
public function lst(){
//商品列表页
$model=D('category');
$data=$model->getTree();
$this->assign(array(
'data'=>$data,
'_page_title'=>'分类列表',
'_page_btn_name'=>'添加新分类',
'_page_btn_link'=>U('add'),
));
$this->display();
}
}
?>
第3步 视图层中做lst页面
注:str_repeat str_repeat() 函数把字符串重复指定的次数 重复8*$v['level']次
插入数据
insert into `p39_category`
(`cat_name`,`parent_id`)
values('男装,女孩,内衣,珠宝','0'),
('个护化妆 ',0) ,
('iphone ',0),
('运动户外 ',0),
('汽车,汽车用品 ',0),
('母婴,玩具乐器 ',0),
('食品,酒类,生鲜,特产',0),
('营养保健',0),
('图书,音像,电子书',0),
('彩票,旅行,充值,票务',0),
('理财,众筹,白条,保险',0),
('大家电',1),
('生活电器',1),
('厨房电器',1),
('个护健康',1),
('五金家族',1),
('冰箱',16)
;
如图所示:
第四步 检验代码
网址输入:http://localhost:8989/php/TpShop/Admin/Category/lst
如图所示:
第五步 做删除功能
波利亚在《怎样解题表》中提出你是否以前见过它?我们在做商品列表页见过,照抄代码即可
public function delete(){
$model=D('category');
if(FALSE!==$model->delete(I('get.id'))){
$this->success('删除成功',U('lst'));
}else{
$this->error("删除失败".$model->getError());
}
}
第2小步 在分类模型添加钩子函数
protected function _before_delete($option){
//先找出所有子分类的ID
$children=$this->getChildren($option['where']['id']);
if($children)
{
$children=implode(',',$children);
$model=\Think\Model();
/*
定义和用法
implode() 函数返回由数组元素组合成的字符串。
注释:implode() 函数接受两种参数顺序。但是由于历史原因,explode() 是不行的,您必须保证 separator 参数在 string 参数之前才行。
注释:implode() 函数的 separator 参数是可选的。但是为了向后兼容,推荐您使用使用两个参数。
注释:该函数是二进制安全的。
$arr = array('Hello','World!','I','love','Shanghai!');
echo implode(" ",$arr);
?>
输出结果:
Hello World! I love Shanghai!
*/
//删除这些子分类
$model->delete($children);
}
}
另一种思路
protected function _before_delete(&$option){
//先找出所有子分类的ID
$children=$this->getChildren($option['where']['id']);
$children[]=$option['where']['id'];
//删除这些子分类
$option['where']['id']=array(
0=>'IN',
1=>implode(',',$children),
);
}