php 实现无限极分类
原始数据
$array = array(
array('id' => 1, 'pid' => 0, 'n' => '河北省'),
array('id' => 2, 'pid' => 0, 'n' => '北京市'),
array('id' => 3, 'pid' => 1, 'n' => '邯郸市'),
array('id' => 4, 'pid' => 2, 'n' => '朝阳区'),
array('id' => 5, 'pid' => 2, 'n' => '通州区'),
array('id' => 6, 'pid' => 4, 'n' => '望京'),
array('id' => 7, 'pid' => 4, 'n' => '酒仙桥'),
array('id' => 8, 'pid' => 3, 'n' => '永年区'),
array('id' => 9, 'pid' => 1, 'n' => '武安市'),
array('id' => 10, 'pid' => 8, 'n' => '永年区镇'),
array('id' => 11, 'pid' => 0, 'n' => '上海市')
);
生成无限极分类
/** 所有的分类
* @parem $array 数组
* @parem $pid ,最高级别,默认为0,输出从pid 级别的数据
* @parem $level 层级,默认0
* */
function getTree($array, $pid =0, $level = 0){ $f_name=__FUNCTION__; // 定义当前函数名 //声明静态数组,避免递归调用时,多次声明导致数组覆盖
static $list = []; foreach ($array as $key => $value){
//第一次遍历,找到父节点为根节点的节点 也就是pid=0的节点
if ($value['pid'] == $pid){
//父节点为根节点的节点,级别为0,也就是第一级
$flg = str_repeat('|--',$level);
// 更新 名称值
$value['n'] = $flg.$value['n'];
// 输出 名称
echo $value['n']."<br/>";
//把数组放到list中
$list[] = $value;
//把这个节点从数组中移除,减少后续递归消耗
unset($array[$key]);
//开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
$f_name($array, $value['id'], $level+1);
}
}
return $list;
}
// 调用
$list=getTree($array);
调用结果:
河北省
|--邯郸市
|--|--永年区
|--|--|--永年区镇
|--武安市
北京市
|--朝阳区
|--|--望京
|--|--酒仙桥
|--通州区
嵌套标签,前端可以(通过选取子节点)全选、取消全选
function getTree($array, $pid =0, $level = 0){ $f_name=__FUNCTION__; // 定义当前函数名 // 空数组 不在执行
if(empty($array))
return; //声明静态数组,避免递归调用时,多次声明导致数组覆盖
static $html;
$html.="<ul>"; foreach ($array as $key => $value){ //第一次遍历,找到父节点为根节点的节点 也就是pid=0的节点
if ($value['pid'] == $pid){
//父节点为根节点的节点,级别为0,也就是第一级
$flg = str_repeat('|--',$level);
// 更新 名称值
$value['n'] = $flg.$value['n'];
$html.=$temp="<li><input type=\"checkbox\" name=\"limit_id[]\" value='".$value['id']."' >".$value['n']; //把这个节点从数组中移除,减少后续递归消耗
unset($array[$key]);
//开始递归,查找父ID为该节点ID的节点,级别则为原级别+1
$vv=$f_name($array, $value['id'], $level+1); // 如果顶级分类下没有一个下级,删除此分类,此步骤可以省略
if(empty($vv) && ($pid<1))
{
$html=str_replace($temp,'',$html);
}
$html.="</li>\r\n"; }
}
$html.="</ul>\r\n"; // 删除多余的 ul 标签
$html=str_replace("<ul></ul>",'',$html);
return $html;
}
html 输出结果
<ul>
<li><input type="checkbox" name="limit_id[]" value='1'>河北省
<ul>
<li><input type="checkbox" name="limit_id[]" value='3'>|--邯郸市
<ul>
<li><input type="checkbox" name="limit_id[]" value='8'>|--|--永年区
<ul>
<li><input type="checkbox" name="limit_id[]" value='10'>|--|--|--永年区镇
</li>
</ul>
</li>
</ul>
</li>
<li><input type="checkbox" name="limit_id[]" value='9'>|--武安市
</li>
</ul>
</li>
<li><input type="checkbox" name="limit_id[]" value='2'>北京市
<ul>
<li><input type="checkbox" name="limit_id[]" value='4'>|--朝阳区
<ul>
<li><input type="checkbox" name="limit_id[]" value='6'>|--|--望京
</li>
<li><input type="checkbox" name="limit_id[]" value='7'>|--|--酒仙桥
</li>
</ul>
</li>
<li><input type="checkbox" name="limit_id[]" value='5'>|--通州区
</li>
</ul>
</li>
</li>
</ul>
jquery 操作全选
//父级选中 自动选中子级,同时选中自己的父级
$('input[type="checkbox"]').change(function(e) {
var checked = $(this).prop("checked"),
container = $(this).parent(),
siblings = container.siblings(); container.find('input[type="checkbox"]').prop({
indeterminate: false,
checked: checked
}); function checkSiblings(el) { var parent = el.parent().parent(),
all = true; el.siblings().each(function() {
return all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);
}); if (all && checked) { parent.children('input[type="checkbox"]').prop({
indeterminate: false,
checked: checked
}); checkSiblings(parent); } else if (all && !checked) { parent.children('input[type="checkbox"]').prop("checked", checked);
parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));
checkSiblings(parent); } else { el.parents("li").children('input[type="checkbox"]').prop({
indeterminate: true,
checked: false
}); } }
checkSiblings(container);
});
// 父级选中 自动选中子级
/*$("input[type=checkbox]").each(function (i,ele){
let _this=$(this);
_this.click(function(){
if(_this.prop('checked')==true)
{
_this.parent().find('ul input').prop('checked',true);
}else
{
_this.parent().find('ul input').prop('checked',false);
}
});
});*/
数组嵌套
引用嵌套,php变量默认的传值方式是按指传递,也就是说 假如说 遍历顺序是 河北省 邯郸市 当遍历到河北省时需要把河北省放到tree中,遍历到邯郸市时,需要把邯郸市放到河北省的子节点数组中,所以这里用到了引用传递,当你对河北省做更改时,tree数组中的河北省也一并做了更改
function getTree($list, $pid = 0)
{
$tree = [];
if (!empty($list)) {
$newList = []; foreach ($list as $k => $v) {
$newList[$v['id']] = $v;
}
foreach ($newList as $value ) {
if ($pid == $value['pid']) {
$tree[] = &$newList[$value['id']];
} elseif (isset($newList[$value['pid']]))
{
$newList[$value['pid']]['items'][] = &$newList[$value['id']];
}
}
// 如果顶级分类下没有一个下级,删除此分类,此步骤可以省略
foreach ($tree as $k=>$v)
{
if(!isset($v['items']) && ($pid<1))
unset($tree[$k]);
}
}
return $tree;
}
// 调用
$list=getTree($array);
var_dump($list);
显示结果
array(2) {
[0]=>
array(4) {
["id"]=>
int(1)
["pid"]=>
int(0)
["n"]=>
string(9) "河北省"
["items"]=>
array(2) {
[0]=>
array(4) {
["id"]=>
int(3)
["pid"]=>
int(1)
["n"]=>
string(9) "邯郸市"
["items"]=>
array(1) {
[0]=>
array(4) {
["id"]=>
int(8)
["pid"]=>
int(3)
["n"]=>
string(9) "永年区"
["items"]=>
array(1) {
[0]=>
array(3) {
["id"]=>
int(10)
["pid"]=>
int(8)
["n"]=>
string(12) "永年区镇"
}
}
}
}
}
[1]=>
array(3) {
["id"]=>
int(9)
["pid"]=>
int(1)
["n"]=>
string(9) "武安市"
}
}
}
[1]=>
array(4) {
["id"]=>
int(2)
["pid"]=>
int(0)
["n"]=>
string(9) "北京市"
["items"]=>
array(2) {
[0]=>
array(4) {
["id"]=>
int(4)
["pid"]=>
int(2)
["n"]=>
string(9) "朝阳区"
["items"]=>
array(2) {
[0]=>
array(3) {
["id"]=>
int(6)
["pid"]=>
int(4)
["n"]=>
string(6) "望京"
}
[1]=>
array(3) {
["id"]=>
int(7)
["pid"]=>
int(4)
["n"]=>
string(9) "酒仙桥"
}
}
}
[1]=>
array(3) {
["id"]=>
int(5)
["pid"]=>
int(2)
["n"]=>
string(9) "通州区"
}
}
}
}
根据子类id查找出所有父级分类信息
/**根据指定id 的查询,所有的父节点
* @parem $id_pid 要查询的id 或者 要查询id的pid;如果传入的是id 包括当前id 值,如果传入id_pid不包括当前id的值
* @parem $array 查分类的数据,在项目使用中此参数可以不传,直接使用sql 查询
* @parem $level 当前id所在层级,默认2
* */
function getParent($id_pid,$array=array(), $level = 2)
{
$f_name=__FUNCTION__; // 定义当前函数名
static $list=array();
//$array=Db::table('table_name')->where('id',$id_pid)->select(); TP5
foreach($array as $k=>$v)
{
if($v['id']== $id_pid)
{ //父级分类id等于所查找的id
$flg = str_repeat('|--',$level);
// 更新 名称值
$v['n'] = $flg.$v['n'];
// 输出 名称
echo $v['n']."<br/>";
$list[]=$v;
// 删除数组
unset($array[$k]);
if($v['pid']>=0)
{
$f_name($v['pid'],$array,$level-1);
}
}
}
return $list;
}
// 调用
getParent(10,$array, $level = 3);
echo "<hr/>";
getParent(8,$array, $level = 3);
调用结果显示
getParent(10,$array, $level = 3);
|--|--|--永年区镇
|--|--永年区
|--邯郸市
-----------------------------------------
getParent(8,$array, $level = 3);
河北省
|--|--|--永年区
|--|--邯郸市
|--河北省
根据父id获得所有下级子类数
/**根据指定id 查询,所有的子节
* @parem $id 要查询的id
* @parem $array 查分类的数据,在项目使用中此参数可以不传,直接使用sql 查询
* @parem $level 层级,默认1
* */
function getSon($id,$array=array(),$level=1)
{
$f_name=__FUNCTION__; // 定义当前函数名
static $list;
//$array=Db::table('table_name')->where('pid',$id)->select(); TP5
foreach ($array as $k => $v)
{
if($v['pid'] == $id)
{
$flg = str_repeat('|--',$level);
// 更新 名称值
$v['n'] = $flg.$v['n'];
// 输出 名称
echo $v['n']."<br/>";
//存放数组中
$list[] = $v;
// 删除查询过的数组
unset($array[$k]);
$f_name($v['id'],$array,$level+1);
}
}
return $list;
}
// 调用
$list=$f_name(1,$array);
调用结果:
|--邯郸市
|--|--永年区
|--|--|--永年区镇
|--武安市
php 实现无限极分类的更多相关文章
- php无限极分类以及递归(thinkphp)
php无限极分类: 无限极分类重点在于表的设计: 1在model中: class CatModel extends Model{ protected $cat = array(); public fu ...
- js实现无限极分类
转载注明出处!!! 转载注明出处!!! 转载注明出处!!! 因为要实现部门通讯录,后台传来的数据是直接从数据库里拿的部门表,所以没有层级分类,只有parentId表示从属关系,所以分类的事情就交给我来 ...
- C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现之方法二:加入缓存机制
在上一篇文章中我用递归方法实现了管理菜单,在上一节我也提到要考虑用缓存,也算是学习一下.Net Core的缓存机制. 关于.Net Core的缓存,官方有三种实现: 1.In Memory Cachi ...
- PHP无限极分类
当你学习php无限极分类的时候,大家都觉得一个字“难”我也觉得很难,所以,现在都还在看,因为工作要用到,所以,就必须得研究研究. 到网上一搜php无限极分类,很多,但好多都是一个,并且,写的很乱, ...
- PHP无限极分类,多种方法|很简单,这里说的很详细,其它地方说的很不好懂
当你学习php无限极分类的时候,大家都觉得一个字"难"我也觉得很难,所以,现在都还在看,因为工作要用到,所以,就必须得研究研究. 到网上一搜php无限极分类,很多,但好多都是一 ...
- C#无限极分类树-创建-排序-读取 用Asp.Net Core+EF实现
今天做一个管理后台菜单,想着要用无限极分类,记得园子里还是什么地方见过这种写法,可今天找了半天也没找到,没办法静下心来自己写了: 首先创建节点类(我给它取名:AdminUserTree): /// & ...
- 谈一次php无限极分类的案例
作者:白狼 出处:http://www.manks.top/php_tree_deep.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追 ...
- PHP无限极分类生成树方法,无限分级
你还在用浪费时间又浪费内存的递归遍历无限极分类吗,看了该篇文章,我觉得你应该换换了.这是我在OSChina上看到的一段非常精简的PHP无限极分类生成树方法,巧在引用,整理分享了. function g ...
- php之无限极分类
首先建立分类信息表: CREATE TABLE IF NOT EXISTS `category` ( `categoryId` smallint(5) unsigned NOT NULL AUTO_I ...
- PHP无限极分类实现
简单版的PHP生成无限极分类代码.其中包括了数据库设计.以及输出分类HTML代码. SQL代码 CREATE TABLE `district` ( `id` int(10) unsigned NOT ...
随机推荐
- Tarjan的强连通分量算法
Tarjan算法用于寻找图G(V,E)中的所有强连通分量,其时间复杂度为O(|V|+|E|). 所谓强连通分量就是V的某个极大子集,其中任意两个结点u,v在图中都存在一条从u到v的路径. Tarjan ...
- 四.python数据类型,语句
Python基础 阅读: 120476 Python是一种计算机编程语言.计算机编程语言和我们日常使用的自然语言有所不同,最大的区别就是,自然语言在不同的语境下有不同的理解,而计算机要根据编程语言执行 ...
- 微信WeixinJSBridge API 屏蔽右上角分享等常用方法
WeixinJSBridge这个API有几个功能还是相当有用的,比如: 1.隐藏微信网页右上角的按钮(...按钮):开发者可以用这个功能来禁止当前页面被分享 2.隐藏微信网页底部的导航栏(比如前进后退 ...
- caret 分类回归树 用法
http://topepo.github.io/caret/feature-selection-overview.html
- 正则表达式复习 (?<=) (?=)
1.首先值得一说的是"<" 和">" 不是元字符 "."是元字符 ,连接字符"-",即使在字符组内部也不一定 ...
- datetime 2017-10-21 10:09:02.560 转年月日的时间类型
sql语句时间转年月日格式: 适用于多种时间格式 select REPLACE(STUFF(CONVERT(char(10), REPLACE(CONVERT(varchar(10),'2017-1 ...
- (转)MongoDB入门分享-笔记整理精选
原文地址:http://www.cnblogs.com/Kummy/p/3372729.html 最近在学习MongoDB,怕以后忘记,自己做了一个整理,给不知道的小伙伴一起分享学习一下. 第一步&g ...
- 福大软工1816|K班—alpha冲刺
Part.1 开篇 队名:彳艮彳亍团队 组长博客:戳我进入 作业博客:班级博客本次作业的链接 Part.2 成员汇报 组员1(组长)柯奇豪 过去两天完成了哪些任务 了解前端方面的相关内容,便于后续对进 ...
- background-image属性的设置
对于图片,首先我们先想到是背景图片.因为我们许许多的装饰都是用背景图片来实现的.既然这样,那么就从CSS控制背景图片讲起吧.1.CSS控制背景图片: 对于一个网页,我们开始设计的时候,可能没有过 ...
- Snapshot--使用脚本创建快照
USE master; SET NOCOUNT ON; GO ); --数据库名 );--快照名 );--保存路径 SET @dbname='DB1'; SET @snapname='DB1_SNAP ...