实现无限级分类一般只用一个数据表,通常可通过递归和非递归两种方法来实现。递归方法必须使用递归调用方式才能进行数据遍历,删除等操作,所以需要发送多次查询数据库语句,非常影响执行效率。那么非递归该怎样来实现无限分类呢?简单来说可用一张表四个字段和一条语句来实现。
1、一张表四个字段
1 | DROP TABLE IF EXISTS `wb_columns`; |
2 | CREATE TABLE `eway_columns` ( |
3 | `colId` smallint (5) unsigned NOT NULL AUTO_INCREMENT, |
4 | `colPid` smallint (5) unsigned NOT NULL DEFAULT '0' , |
5 | `colPath` varchar (100) NOT NULL DEFAULT '' , |
6 | `colTitle` varchar (100) NOT NULL DEFAULT '' , |
8 | KEY `colPath` (`colPath`) |
9 | ) ENGINE=MyISAM CHARSET=utf8; |
2、一条语句
1 | SELECT concat(colPath, '-' ,colId) AS bpath, colId,colPid,colPath, colTitle, FROM " . C('DB_PREFIX') . " columns ORDER BY bpath, colId; |
在上面的一条语句的SQL查询中,使用MYSQL中的concat函数将colPath和colId字段通过字符"-"连接起来,并将该字段设置为bpath别名。然后先通过bpathpb 字段进行排序,如果有相同的路径再通过colId字段进行排序,这样就会以分类的各级层次结构将结果返回。
下面是在thinkphp3.1中非递归无限级分类的实现代码
03 | * 分类Columns的控制器ColumnsAction.class.php |
05 | class ColumnsAction extends Action{ |
07 | public function index(){ |
09 | $catarray = $this ->Catlist(); |
11 | $this ->assign( 'catarray' , $catarray ); |
17 | public function insert() { |
18 | $catarray = $this ->Catlist(); |
20 | $this ->assign( 'catarray' , $catarray ); |
26 | public function add() { |
28 | if ( $vo = $D ->create()) { //因为使用模型类处理,自动完成必须通过create方法才能生效。 |
31 | $this ->success( "添加成功" ); |
37 | $this ->error( $D ->getError()); |
44 | $list = $Columns ->query( "SELECT concat(colPath,'-',colId) AS bpath, colId,colPid,colPath, colTitle, FROM " . C( 'DB_PREFIX' ) . "columns ORDER BY bpath, colId" ); |
46 | foreach ( $list as $k => $v ) { |
47 | $list [ $k ][ 'count' ] = count ( explode ( '-' , $v [ 'bpath' ])); |
48 | $list [ $k ][ 'total' ] = $Module ->where( 'catid=' . $v [ 'colId' ])-> count (); |
50 | if ( $v [ 'colPid' ] <> 0) { |
51 | for ( $i = 0; $i < $list [ $k ][ 'count' ] * 2; $i ++) { |
56 | $list [ $k ][ 'space' ] = $str ; |
64 | * 分类Columns的模型类ColumnsModel.class.php |
65 | * 作用:在添加分类或修改分类时自动处理colPath字段并保存到数据库中 |
66 | * callback :回调方法 ,表示填充的内容是一个当前模型的方法 |
67 | * Model:: MODEL_INSERT 或者1新增数据时候验证 |
68 | * Model:: MODEL_UPDATE 或者2编辑数据时候验证 |
69 | * Model:: MODEL_BOTH 或者3 全部情况下验证(默认),这里选择该验证。 |
72 | class ColumnsModel extends Model{ |
73 | protected $_auto = array ( //thinkphp的自动填充 |
74 | array ( 'colPath' , 'colPath' ,3, 'callback' ), |
79 | $colPid =isset( $_POST [ 'colPid' ])?(int) $_POST [ 'colPid' ]:0; |
80 | $colId = $_POST [ 'colId' ]; |
85 | $fat = $this ->where( 'colId=' . $colPid )->find(); //查询的是父级ID |
86 | $data = $fat [ 'colPath' ]. '-' . $fat [ 'colId' ]; //得到父级的colPath,连上父级ID,返回的是子级的colPath |
需要注意的是,这是使用模型的自动完成功能,所以必须通过create方法才能生效,Create方法创建的数据对象是保存在内存中,并没有实际写入到数据库中,直到使用add方法才真正写入数据库中。