2款PHP无限级分类实例代码


Posted in PHP onNovember 11, 2015

本文章总结了两款PHP无限级分类实现程序代码,有需要学习的朋友可参考一下。
主要思路:首先看第三行和第四行,父类ID(PARENTID)的值是1,表示属于id=1这个类的子类,而,一,二两行因为是一级分类,没有上级分类,所以父类ID(PARENTID)的值是0,表示初级分类,依次类推便实现了无限级分类。最终的效果是:
├一级分类A
├─┴二级分类A
├─┴二级分类B
├一级分类B
然后就是程序,这里以PHP作为描述语言,可以很方便的改成其他语言,因为原理相似,就是一个递归而已。

<?php
$dbhost = "localhost";  // 数据库主机名
$dbuser = "root";  // 数据库用户名
$dbpd = "123456";  // 数据库密码
$dbname = "test";  // 数据库名
mysql_connect($dbhost,$dbuser,$dbpd);    //连接主机
mysql_select_db($dbname);    //选择数据库
mysql_query("SET NAMES 'utf8'");
display_tree("├",0);
function display_tree($tag,$classid) {
  $result = mysql_query("
    SELECT *
    FROM ylmf_class
    WHERE parentid = '" . $classid . "'
    ;"
  );
  while ($row = mysql_fetch_array($result)) {
    // 缩进显示节点名称
 echo $tag.$row['classname'] . "<br/>";
    //再次调用这个函数显示子节点的子节点
 display_tree($tag."─┴",$row['id']);
  }
}
?>

在表格中显示
TreeTable通过对单元格的行合并和列合并实现了无限层级也能较好的展示层级架构。
1.构建ID/PID/NAME的数组,后期可通过数据库生成的动态数据。Tree算法请点击

array(
* 1 => array('id'=>'1','parentid'=>0,'name'=>'一级栏目一'),
* 2 => array('id'=>'2','parentid'=>0,'name'=>'一级栏目二'),
* 3 => array('id'=>'3','parentid'=>1,'name'=>'二级栏目一'),
* 4 => array('id'=>'4','parentid'=>1,'name'=>'二级栏目二'),
* 5 => array('id'=>'5','parentid'=>2,'name'=>'二级栏目三'),
* 6 => array('id'=>'6','parentid'=>3,'name'=>'三级栏目一'),
* 7 => array('id'=>'7','parentid'=>3,'name'=>'三级栏目二')
* )

2. 导入TreeTable类库。
代码如下:

import('@.ORG.Util.TableTree'); //Thinkphp导入方法

3. 生成TreeTable HTML代码

$treeTable->init($treearr);
echo $treeTable->get_treetable();

注意:get_treetable()只生产表体部门,<TALBE></TABLE>请自行构建。
完整代码

<?php
/**
* File name: TreeTable.class.php
* Description: 通用的表格无限级分类
* */
/**
* 表格展示无限分类是将无线分类已表格的形式表现出来,更好的能体现出分类的所属关系
* 使用方法:
* 1. 实例化分类
* $treeTable = new TreeTable();
* 2. 初始化分类,$treearr必须是一个多维数组且包含 id,parentid,name字段
* $treeTable->init($treearr);
* 3. 获取无限分类HTML代码
* echo $treeTable->get_treetable();
* */
class TreeTable {
/**
* 生成树型结构所需要的2维数组
* @var array
*/
public $arr = array();
/**
* 表格列数
* @var int
*/
public $columns = 0;
/**
* 表格行数
* @var int
*/
public $rows = 0;
/**
* 初始化TreeTable数据
* @param array 2维数组
* array(
* 1 => array('id'=>'1','parentid'=>0,'name'=>'一级栏目一'),
* 2 => array('id'=>'2','parentid'=>0,'name'=>'一级栏目二'),
* 3 => array('id'=>'3','parentid'=>1,'name'=>'二级栏目一'),
* 4 => array('id'=>'4','parentid'=>1,'name'=>'二级栏目二'),
* 5 => array('id'=>'5','parentid'=>2,'name'=>'二级栏目三'),
* 6 => array('id'=>'6','parentid'=>3,'name'=>'三级栏目一'),
* 7 => array('id'=>'7','parentid'=>3,'name'=>'三级栏目二')
* )
*/
public function init($arr=array()){
if(!is_array($arr)) return false;
foreach ($arr as $k=>$v) {
$this->arr[$v['id']] = $v;
}
foreach ($this->arr as $k => $v){
$this->arr[$k]['column'] = $this->get_level($v['id']); // Y轴位置
$this->arr[$k]['arrchildid'] = $this->get_arrchildid($v['id']); // 所有子节点
$this->arr[$k]['arrparentid'] = $this->get_arrparentid($v['id']); // 所有父节点
$this->arr[$k]['child_bottom_num'] = $this->get_child_count($v['id']); // 所有底层元素节点
}
$this->columns = $this->get_columns(); // 总行数
$this->rows = $this->get_rows(); // 总列数
// 按照arrparentid和id号进行排序
$this->sort_arr();
foreach ($this->arr as $k => $v){
$this->arr[$k]['row'] = $this->get_row_location($v['id']); // X轴位置
$this->arr[$k]['rowspan'] = $v['child_bottom_num']; // 行合并数
$this->arr[$k]['colspan'] = $v['child_bottom_num'] == 0 ? $this->columns - $v['column'] + 1 : 0; //列合并数
}
return $this->get_tree_arr();
}
/**
* 获取数组
* */
public function get_tree_arr(){
return is_array($this->arr) ? $this->arr : false;
}
/**
* 按arrparentid/id号依次重新排序数组
* */
public function sort_arr(){
// 要进行排序的字段
foreach ($this->arr as $k => $v){
$order_pid_arr[$k] = $v['arrparentid'];
$order_iscost[] = $v['sort'];
$order_id_arr[$k] = $v['id'];
}
// 先根据arrparentid排序,再根据排序,id号排序
array_multisort(
$order_pid_arr, SORT_ASC, SORT_STRING,
$order_iscost, SORT_DESC, SORT_NUMERIC,
$order_id_arr, SORT_ASC, SORT_NUMERIC,
$this->arr);
// 获取每一个节点层次
for ($column = 1; $column <= $this->columns; $column++) {
$row_level = 0;
foreach ($this->arr as $key => $node){
if ($node['column'] == $column){
$row_level++;
$this->arr[$key]['column_level'] = $row_level;
}
}
}
// 重新计算以ID作为键名
foreach ($this->arr as $k=>$v) {
$arr[$v['id']] = $v;
}
$this->arr = $arr;
}
/**
* 得到父级数组
* @param int
* @return array
*/
public function get_parent($myid){
$newarr = array();
if(!isset($this->arr[$myid])) return false;
$pid = $this->arr[$myid]['parentid'];
$pid = $this->arr[$pid]['parentid'];
if(is_array($this->arr)){
foreach($this->arr as $id => $a){
if($a['parentid'] == $pid) $newarr[$id] = $a;
}
}
return $newarr;
}
/**
* 得到子级数组
* @param int
* @return array
*/
public function get_child($myid){
$a = $newarr = array();
if(is_array($this->arr)){
foreach($this->arr as $id => $a){
if($a['parentid'] == $myid) $newarr[$id] = $a;
}
}
return $newarr ? $newarr : false;
}
/**
* 获取当前节点所在的层级
* @param $myid 当前节点ID号
* */
public function get_level($myid, $init = true){
static $level = 1;
if($init) $level = 1;
if ($this->arr[$myid]['parentid']) {
$level++;
$this->get_level($this->arr[$myid]['parentid'], false);
}
return $level;
}
/**
* 获取当前节点所有底层节点(没有子节点的节点)的数量
* @param $myid 节点ID号
* @param $init 第一次加载将情况static变量
* */
public function get_child_count($myid, $init = true){
static $count = 0;
if($init) $count = 0;
if(!$this->get_child($myid) && $init) return 0;
if($childarr = $this->get_child($myid)){
foreach ($childarr as $v){
$this->get_child_count($v['id'], false);
}
}else{
$count++;
}
return $count;
}
/**
* 获取节点所有子节点ID号
* @param $catid 节点ID号
* @param $init 第一次加载将情况static初始化
* */
public function get_arrchildid($myid, $init = true) {
static $childid;
if($init) $childid = '';
if(!is_array($this->arr)) return false;
foreach($this->arr as $id => $a){
if($a['parentid'] == $myid) {
$childid = $childid ? $childid.','.$a['id'] : $a['id'];
$this->get_arrchildid($a['id'], false);
}
}
return $childid ;
}
/**
* 获取该节点所有父节点ID号
* @param $id 节点ID号
* */
public function get_arrparentid($id, $arrparentid = '') {
if(!is_array($this->arr)) return false;
$parentid = $this->arr[$id]['parentid'];
if($parentid > 0) $arrparentid = $arrparentid ? $parentid.','.$arrparentid : $parentid;
if($parentid) $arrparentid = $this->get_arrparentid($parentid, $arrparentid);
return $arrparentid;
}
/**
* 获取节点所在地行定位
* @param $myid 节点ID号
*/
public function get_row_location($myid){
$nodearr = $this->arr;
// 获取每一个节点所在行的位置
foreach ($nodearr as $key => $node){
if($myid == $node['id']) {
$node_row_count = 0;
$arrparentid = explode(',', $node['arrparentid']);
// 所有父节点小于当前节点层次的底层节点等于0的元素
foreach ($arrparentid as $pid){
foreach ($nodearr as $node_row){
if($node_row['column'] == $nodearr[$pid]['column'] && $nodearr[$pid]['column_level'] > $node_row['column_level'] && $node_row['child_bottom_num'] == 0){
$node_row_count ++;
}
}
}
// 所有当前节点并且节点层次(rowid_level)小于当前节点层次的个数
foreach ($nodearr as $node_row){
if($node['column'] == $node_row['column'] && $node_row['column_level'] < $node['column_level']){
$node_row_count += $node_row['child_bottom_num'] ? $node_row['child_bottom_num'] : 1;
}
}
$node_row_count++;
break;
}
}
return $node_row_count;
}
/**
* 获取表格的行数
* */
public function get_rows(){
$row = 0;
foreach ($this->arr as $key => $node){
if($node['child_bottom_num'] == 0){
$rows++; // 总行数
}
}
return $rows;
}
/**
* 获取表格的列数
* */
public function get_columns(){
$columns = 0 ;
foreach ($this->arr as $key => $node){
if($node['column'] > $columns){
$columns = $node['column']; // 总列数
}
}
return $columns;
}
/**
* 获取分类的表格展现形式(不包含表头)
* */
public function get_treetable(){
$table_string = '';
for($row = 1; $row <= $this->rows; $row++){
$table_string .= "rt<tr>";
foreach ($this->arr as $v){
if($v['row'] == $row){
$rowspan = $v['rowspan'] ? "rowspan='{$v['rowspan']}'" : '';
$colspan = $v['colspan'] ? "colspan='{$v['colspan']}'" : '';
$table_string .= "rtt<td {$rowspan} {$colspan}>
{$v['name']}
</td>";
}
}
$table_string .= "rt</tr>";
}
return $table_string;
}
}
?>

希望本文所述对大家学习php程序设计有所帮助。

PHP 相关文章推荐
在线竞拍系统的PHP实现框架(一)
Oct 09 PHP
PHP4与PHP3中一个不兼容问题的解决方法
Oct 09 PHP
PHP curl模拟浏览器采集阿里巴巴的实现代码
Apr 20 PHP
一个PHP缓存类代码(附详细说明)
Jun 09 PHP
php遍历所有文件及文件夹的方法深入解析
Jun 08 PHP
PHP设计模式之解释器模式的深入解析
Jun 13 PHP
用PHP实现弹出消息提示框的两种方法
Dec 17 PHP
php防止sql注入简单分析
Mar 18 PHP
10个超级有用的PHP代码片段果断收藏
Sep 23 PHP
php5.4传引用时报错问题分析
Jan 22 PHP
详解Yii2高级版引入bootstrap.js的一个办法
Mar 21 PHP
PHP实现对xml的增删改查操作案例分析
May 19 PHP
PHP中set error handler函数用法小结
Nov 11 #PHP
php实现Session存储到Redis
Nov 11 #PHP
PHP防止刷新重复提交页面的示例代码
Nov 11 #PHP
PHP用mb_string函数库处理与windows相关中文字符及Win环境下开启PHP Mb_String方法
Nov 11 #PHP
深入php内核之php in array
Nov 10 #PHP
谈谈你对Zend SAPIs(Zend SAPI Internals)的理解
Nov 10 #PHP
php实现可运算的验证码
Nov 10 #PHP
You might like
jQuery源码分析-05异步队列 Deferred 使用介绍
2011/11/14 Javascript
jQuery中bind与live的用法及区别小结
2014/01/27 Javascript
JavaScript运行时库属性一览表
2014/03/14 Javascript
jquery判断小数点两位和自动删除小数两位后的数字
2014/03/19 Javascript
JS数组合并push与concat区别分析
2015/12/17 Javascript
javascript中的3种继承实现方法
2016/01/27 Javascript
jQuery基于函数重载实现自定义Alert函数样式的方法
2016/07/27 Javascript
JavaScript实现简易的天数计算器实例【附demo源码下载】
2017/01/18 Javascript
初学者AngularJS的环境搭建过程
2017/10/27 Javascript
基于vue.js 2.x的虚拟滚动条的示例代码
2018/01/23 Javascript
vue :src 文件路径错误问题的解决方法
2018/05/15 Javascript
详解JS转换数值函数Number()、parseInt()、parseFloat()
2018/08/24 Javascript
[02:45]DOTA2英雄基础教程 伐木机
2013/12/23 DOTA
[03:17]2016完美“圣”典风云人物:冷冷专访
2016/12/08 DOTA
Python字符串的encode与decode研究心得乱码问题解决方法
2009/03/23 Python
跟老齐学Python之编写类之三子类
2014/10/11 Python
Python内置函数Type()函数一个有趣的用法
2015/02/18 Python
用Python制作简单的钢琴程序的教程
2015/04/01 Python
python计算牛顿迭代多项式实例分析
2015/05/07 Python
Python入门之modf()方法的使用
2015/05/15 Python
python用模块zlib压缩与解压字符串和文件的方法
2016/12/16 Python
Python实现发送与接收邮件的方法详解
2018/03/28 Python
Python3.5内置模块之random模块用法实例分析
2019/04/26 Python
python orm 框架中sqlalchemy用法实例详解
2020/02/02 Python
改变生活的男士内衣:SAXX Underwear
2019/08/28 全球购物
英国最大的割草机购买网站:Just Lawnmowers
2019/11/02 全球购物
为什么group by 和order by会使查询变慢
2014/05/16 面试题
请解释一下webService? 如何用.net实现webService
2014/06/09 面试题
金融专业个人求职信
2013/09/22 职场文书
丧事主持词大全
2014/04/02 职场文书
汽车服务工程专业自荐信
2014/09/02 职场文书
三行辞职书范文
2015/02/26 职场文书
金榜题名主持词
2015/07/02 职场文书
商业计划书范文
2019/04/24 职场文书
在Spring-Boot中如何使用@Value注解注入集合类
2021/08/02 Java/Android
Hive HQL支持2种查询语句风格
2022/06/25 数据库