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防注入安全代码
Apr 09 PHP
ThinkPHP采用模块和操作分析
Apr 18 PHP
PHP获取搜索引擎关键字来源的函数(支持百度和谷歌等搜索引擎)
Oct 03 PHP
php列出一个目录下的所有文件的代码
Oct 09 PHP
解析PHP计算页面执行时间的实现代码
Jun 18 PHP
php 强制下载文件实现代码
Oct 28 PHP
php获取指定日期之间的各个周和月的起止时间
Nov 24 PHP
如何使用jQuery+PHP+MySQL来实现一个在线测试项目
Apr 26 PHP
php比较两个字符串长度的方法
Jul 13 PHP
PHP入门教程之表单与验证实例详解
Sep 11 PHP
PHP批量修改文件名称的方法分析
Feb 27 PHP
浅谈Laravel中的三种中间件的作用
Oct 13 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
几个php应用技巧
2008/03/27 PHP
PHP下通过exec获得计算机的唯一标识[CPU,网卡 MAC地址]
2011/06/09 PHP
PHP 获取文件权限函数介绍
2013/07/11 PHP
ThinkPHP自动完成中使用函数与回调方法实例
2014/11/29 PHP
浅谈laravel数据库查询返回的数据形式
2019/10/21 PHP
JavaScript支持的最大递归调用次数分析
2014/06/24 Javascript
jQuery Ajax中的事件详细介绍
2015/04/16 Javascript
JS中Location使用详解
2015/05/12 Javascript
JavaScript通过Date-Mask将日期转换成字符串的方法
2015/06/04 Javascript
解决jquery无法找到其他父级子集问题的方法
2016/05/10 Javascript
前端框架Vue.js中Directive知识详解
2016/09/12 Javascript
详解angular 中的自定义指令之详解API
2017/06/20 Javascript
JavaScript实现简单音乐播放器
2020/04/17 Javascript
jQuery利用FormData上传文件实现批量上传
2018/12/04 jQuery
vue项目打包上传github并制作预览链接(pages)
2019/04/19 Javascript
如何在微信小程序里面退出小程序的方法
2019/04/28 Javascript
使用 Element UI Table 的 slot-scope方法
2019/10/10 Javascript
Javascript 类型转换、封闭函数及常见内置对象操作示例
2019/11/15 Javascript
[49:59]KG vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Pycharm技巧之代码跳转该如何回退
2017/07/16 Python
Python采集猫眼两万条数据 对《无名之辈》影评进行分析
2018/12/05 Python
Django使用redis缓存服务器的实现代码示例
2019/04/28 Python
Python 使用多属性来进行排序
2019/09/01 Python
python3实现用turtle模块画一棵随机樱花树
2019/11/21 Python
Python .py生成.pyd文件并打包.exe 的注意事项说明
2021/03/04 Python
websocket+sockjs+stompjs详解及实例代码
2018/11/30 HTML / CSS
乌克兰数字设备、配件和智能技术的连锁商店:KTC
2020/08/18 全球购物
线程同步的方法
2016/11/23 面试题
学校大课间活动方案
2014/01/30 职场文书
经理秘书求职自荐信范文
2014/03/23 职场文书
对孩子的寄语
2014/04/09 职场文书
小学五年级学生评语
2014/04/22 职场文书
赢在执行观后感
2015/06/16 职场文书
幼儿园开学家长寄语(2016春季)
2015/12/03 职场文书
初中班主任心得体会
2016/01/07 职场文书
关于windows server 2012 DC 环境 重启后蓝屏代码:0xc00002e2的问题
2022/05/25 Servers