PHP实现了无限类的分类(没有递归)。

在发展中经常用到一类无限的分类,例如:部门结构,文章分类,无限类分类的困难在于输出和查询,例如

这篇文章被列为名单。
查找分类A中所有分类所包含的文章。


1。实现原理

常见的几种实现方法的优点和缺点。提出了一种改进的前序遍历树的数据结构,方便输出和查询,但它是有点复杂的移动分类和传统的理解。

2。数据结构



< PHP
数组=
阵列('id' = > 1,'fid= > 0,'title'china= >),
阵列('id' = > 2,'fid= > 1,标题= >江苏),
阵列('id' = > 3,'fid= > 1,标题= >安徽),
阵列('id' = > 4,'fid= > 8,标题= >江阴),
阵列('id' = > 5,'fid= > 3,标题= >芜湖),
阵列('id' = > 6,'fid= > 3,标题= >合肥),
阵列('id' = > 7,'fid= > 3,标题= >蚌埠),
阵列('id' = > 8,'fid= > 8,标题= >无锡)
);
>



分类树是通过父ID的层次序列在分类之间形成的,在这个系列中要注意的一点是分类A的FID不能是它的子类的ID。

当使用此数据结构进行输出时,最常用的算法是递归。熟悉PHP语言的朋友必须知道PHP不擅长递归,而且递归的数量是有限的(大约100倍,因为操作系统和配置)。

由于所有递归都可以通过循环实现,本文根据PHP语言的特点,编写了一套关于无限级分类的函数,比递归实现更高效。

三.输出UL表形式

将上述数据输出到以下HTML




江苏


无锡


江阴






安徽

芜湖
合肥
蚌埠






这种HTML结构在前端非常方便(使用Javascript和CSS构建一个可折叠的树):






4。输出选项列表表单





江苏
无锡
江阴
安徽
芜湖
合肥
蚌埠



具体实施程序如下:



< PHP
/ / get_tree_option()返回一个数组,每个元素和增加深度(深度),直接输出。
$选项= get_tree_option($列表,1);
foreach(美元美元期权OP){
回波。str_repeat(
}
>




5。查找某个类别的所有子类




< PHP
美元儿童= get_tree_child($列表,0);
回声崩溃('',美元儿童); / /输出:1,3,2,7,6,5,8,4
>


6。找到某一类别的所有父母




< PHP
美元儿童= get_tree_parent($列表,4);
回声崩溃(','美元儿童); / / 8, 2, 10
>



7。相关函数




< PHP
功能get_tree_child($美元数据,FID){
结果=数组();
包括美元=阵列($ FID);
{做
CID阵列(美元)=;
$标志= false;
foreach(包括美元美元FID){
对于($ =计数(数据)- 1;$ i = 0;$ i){
$ = $;
如果(合结{ 'fid} = = $ FID){
array_splice(美元的数据,我,1);
结果{ } =美元美元结{ 'id' };
CIDS { } =美元美元结{ 'id' };
$标志=真;
}
}
}
包括美元= $ CIDS;
}($ = true);
返回$结果;
}

功能get_tree_parent($数据,$id){
结果=数组();
$ obj =阵();
foreach($数据达节点){
$ obj { $结{ 'id' } } = $节点;
}

价值= isset($ obj { $id }){ }:美元美元的对象ID无效;
当($值){
$ = null;
foreach($数据达节点){
如果(合结{ 'id' } = =价值{ 'fid ' }){
美元美元的节点ID = { 'id' };
结果{ } =美元美元结{ 'id' };
打破;
}
}
如果($ = NULL){
结果{ } =美元价值'fid'} {;
}
价值= isset($ obj { $id }){ }:美元美元的对象ID无效;
}
unset($ obj);
返回$结果;
}

功能get_tree_ul($美元数据,FID){
$堆栈=数组($ FID);
$子数组();
added_left美元=阵();
added_right美元=阵();
html_left美元=阵();
html_right美元=阵();
$ obj =阵();
$循环= 0;
foreach($数据达节点){
PID =美元美元'fid节点{ };
如果(!isset($孩子{ $ PID })){
$子数组();
}
array_push($孩子{ $ PID },{ $节点'id' });
$ obj { $结{ 'id' } } = $节点;
}

当(计数(堆栈)> 0){
$ $堆栈{ 0 };
$标志= false;
美元($ obj设置节点= { $id }){ }:美元美元的对象ID无效;
如果(isset($孩子{ $id })){
美元美元美元CIDS =孩子{身份};
美元($ CID)长度=计数;
对于($ i = $长度1;$ i = 0;$ i){
array_unshift(合栈,CID美元{ $我});
}
$ obj { $ CIDS { 1 } } { $长'islastchild} =真;
$ obj { $ CIDS { 0 } } { } =真'isfirstchild;
$标志=真;
}
如果($ id)!= $ $节点!Isset ($added_left{$id})) {
如果(isset(合结{ 'isfirstchild'} isset(){ }为节点'islastchild)){
html_left美元{ } =;
} else if(isset(合结{ 'isfirstchild ' })){
html_left美元{ } =;
} else if(isset(合结{ 'islastchild ' })){
html_left美元{ } =;
{人}
html_left美元{ } =;
}
html_left美元{ } =($旗= true){ } } { $节点标题:{ } } { $节点标题;
added_left { } =美元美元的真实身份;
}
如果($ id)!= $ $节点!isset($ added_right { $id })){
html_right美元{ } =($旗= true)';
added_right { } =美元美元的真实身份;
}

如果($ = false){
如果($节点){
美元美元美元CIDS =孩子{ { } } 'fid节点;
(我=计数为美元(美元1美元CIDS);我> = 0;$我--){
如果($ CIDS { $我} = = $id){
array_splice($孩子{ { } } $节点'fid ',我,1);
打破;
}
}
如果(计数($孩子{ { } } $节点'fid)= = 0){
$孩子{ $结{ } } = null 'fid;
}
}
array_push(html_left美元,array_pop($ html_right));
array_shift($堆栈);
}
$循环+ +;
如果(合环> 5000)返回html_left美元;
}
unset($孩子);
unset($ obj);
返回崩溃('',html_left美元);
}

功能get_tree_option($美元数据,FID){
$堆栈=数组($ FID);
$子数组();
$ =数组();
$选项=数组();
$ obj =阵();
$循环= 0;
$深度= 1;
foreach($数据达节点){
PID =美元美元'fid节点{ };
如果(!isset($孩子{ $ PID })){
$子数组();
}
array_push($孩子{ $ PID },{ $节点'id' });
$ obj { $结{ 'id' } } = $节点;
}

当(计数(堆栈)> 0){
$ $堆栈{ 0 };
$标志= false;
美元($ obj设置节点= { $id }){ }:美元美元的对象ID无效;
如果(isset($孩子{ $id })){
对于($ i =计数($孩子{身份证})- 1;$ I = 0;$ I){
array_unshift(合栈,孩子{身份} {美元美元美元我});
}
$标志=真;
}
如果($ id)!= $ $节点!isset($加{ $id })){
{ } =节点'depth美元美元的深度;
$选项;
添加$ {真};
}
如果($ = TRUE){
深度+ +;
{人}
如果($节点){
为($我=计数($孩子{ { } } $节点'fid)1美元= 0;我>;我--){
如果($孩子{ { } } $节点'fid{ } = =我美元美元ID){
array_splice($孩子{ { } } $节点'fid ',我,1);
打破;
}
}
如果(计数($孩子{ { } } $节点'fid)= = 0){
$孩子{ $结{ } } = null 'fid;
深度—;
}
}
array_shift($堆栈);
}
$循环+ +;
如果($循环> 5000)返回$选项;
}
unset($孩子);
unset($ obj);
返回$选项;
}
>





这不是在使用递归PHP实现无限分类的情况下,希望对大家有所帮助。