在最近的项目中,我需要从数据库中挑选出带【未经授权禁止转载】转载请注明出处:www.tangshuang.net有层级关系的数据,并根据记录的paren本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。t_id构建数据之间的父子关系,最终形成【作者:唐霜】原创内容,盗版必究。一个树状结构的父子孙关系结构,并用数组的原创内容,盗版必究。【作者:唐霜】形式保存起来。经过搜索和研究,最终找到了【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。下方的算法代码,仅做参考。
本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。ang.net本文作者:唐霜,转载请注明出处。首先,查询得到的数据以数组的形式返回:
【访问 www.tangshuang.n【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshu转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。ang.net【作者:唐霜】array(
array('id' => 5,'parent_id' => 0,...),
array('id' => 9,'parent_id' => 0,...),
array('id' => 12,'parent_id' => 5,...),
array('id' => 19,'parent_id' => 5,...),
array('id' => 21,'parent_id' => 0,...),
array('id' => 23,'parent_id' => 12,...),
array('id' => 24,'parent_id' => 12,...),
array('id' => 26,'parent_id' => 23,...),
array('id' => 29,'parent_id' => 9,...),
array('id' => 31,'parent_id' => 12,...),
...
)
通过观察,我们可以发现顶级数组是由包含i【转载请注明来源】未经授权,禁止复制转载。d,parent_id的数组组成的,这些本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。数组之间存在着一定的父子关系,而且仅以p著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netarent_id的形式表现出来。现在,我【原创不易,请尊重版权】【作者:唐霜】们实际上想要得到下面的结果:
著作权归作者所有,禁止商业用途转载。【转载请注明来源】【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。array(
array(
'id' => 5,
'children' => array(
array(
'id' => 12,
'children' => array(
array(
'id' => 23,
'children' => array(
array('id' => 26)
)
),
array('id' => 24),
array('id' => 31)
)
),
array('id' => 19)
)
),
array(
'id' => 9,
'children' => array(
array('id' => 29)
)
),
array('id' => 21),
...
)
也就是通过数组的形式,用一个childr【本文受版权保护】【本文受版权保护】en元素来包含该元素的子元素,并且层级分【作者:唐霜】著作权归作者所有,禁止商业用途转载。明。
转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ng.net【未经授权禁止转载】【原创内容,转载请注明出处】【未经授权禁止转载】那么如何来快速实现呢?我们通过下面一个函【本文受版权保护】本文版权归作者所有,未经授权不得转载。数来实现。
【版权所有】唐霜 www.tangshu【版权所有,侵权必究】【本文首发于唐霜的博客】ang.net【作者:唐霜】function array_tree($array) {
$result = array();
$tmp = array();
foreach($array as $item) {
if($item['parent_id'] == 0) {
$i = count($result);
$result[$i] = $item;
$id = $item['id'];
$tmp[$id] = &$result[$i];
}
else {
$id = $item['id'];
$parent_id = $item['parent_id'];
$parent = $tmp[$parent_id];
$i = count($parent['children']);
$tmp[$parent_id]['children'][$i] = $item;
$tmp[$id] = &$tmp[$parent_id]['children'][$i];
}
}
return $result;
}
上面我用红色标注了&符号,具体是【本文受版权保护】未经授权,禁止复制转载。什么意思,及其原理又是怎么实现的呢?
转载请注明出处:www.tangshua著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。ng.net原创内容,盗版必究。&引用是PHP中非常特殊的一种变著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。量引用方式。我们不过多深入的去讲解,简单【作者:唐霜】转载请注明出处:www.tangshuang.net的讲,就是:
转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。ng.net未经授权,禁止复制转载。转载请注明出处:www.tangshua本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。ng.net【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】ang.net【版权所有,侵权必究】【原创内容,转载请注明出处】【转载请注明来源】当$b = &$a时,$b和$a【本文受版权保护】【作者:唐霜】同时引用同一个内容(指针指向同一块内存)转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。,无论$a或$b谁发生变化,这个内容都会【原创不易,请尊重版权】【作者:唐霜】发生变化,进而呈现为$a和$b保持同步的【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】变化。
本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshu【原创不易,请尊重版权】未经授权,禁止复制转载。ang.net
要解除这种引用,只有先将引用释放。可是并【版权所有】唐霜 www.tangshuang.net【转载请注明来源】没有一种运算可以达到释放引用的目的,所以【本文受版权保护】转载请注明出处:www.tangshuang.net我们可以通过unset($a)的方式,也著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】可以通过重新引用另外一个变量来释放原来的本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。引用(但是又和其他变量引用,比如$b =【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。 &$c)。
【作者:唐霜】原创内容,盗版必究。这时,我们再来分析上面的实现函数。
【访问 www.tangshuang.n本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】et 获取更多精彩内容】【版权所有,侵权必究】未经授权,禁止复制转载。$tmp[$id] = &$re转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】sult[$i];
【关注微信公众号:wwwtangshua转载请注明出处:www.tangshuang.net【作者:唐霜】ngnet】【版权所有,侵权必究】这一句保证了当无论$tmp[$id]还是原创内容,盗版必究。未经授权,禁止复制转载。$result[$i]发生变化,都会让另【原创内容,转载请注明出处】【原创内容,转载请注明出处】外一个值同时发生变化。而
转载请注明出处:www.tangshua【未经授权禁止转载】本文作者:唐霜,转载请注明出处。ng.net【访问 www.tangshuang.n【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。$tmp[$parent_id][【转载请注明来源】【版权所有,侵权必究】216;children’]【未经授权禁止转载】【访问 www.tangshuang.net 获取更多精彩内容】[$i] = $item;
【本文受版权保护】【作者:唐霜】未经授权,禁止复制转载。实际上导致$result[$parent【转载请注明来源】【版权所有】唐霜 www.tangshuang.net_id]发生了变化。
【转载请注明来源】【本文受版权保护】用我们上面的数据进行演示验证:
本文版权归作者所有,未经授权不得转载。【本文受版权保护】【作者:唐霜】原创内容,盗版必究。转载请注明出处:www.tangshua未经授权,禁止复制转载。【本文首发于唐霜的博客】ng.net【本文首发于唐霜的博客】[0] => array(R本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】16;id’ => 5原创内容,盗版必究。未经授权,禁止复制转载。,’parent_id未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】217; => 0,…【作者:唐霜】【关注微信公众号:wwwtangshuangnet】)
【版权所有】唐霜 www.tangshu【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】ang.net本文版权归作者所有,未经授权不得转载。$result[0] = array(&本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】#8216;id’ =>【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】; 5,’parent_id【原创不易,请尊重版权】【原创内容,转载请注明出处】’ => 0,R未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】30;)
未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshua原创内容,盗版必究。【转载请注明来源】ngnet】【转载请注明来源】$tmp[5] = &$resu转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。lt[0] // 第一个&出现【作者:唐霜】本文版权归作者所有,未经授权不得转载。了
【作者:唐霜】未经授权,禁止复制转载。原创内容,盗版必究。转载请注明出处:www.tangshua【作者:唐霜】【版权所有,侵权必究】ng.net$tmp[5] = array(R未经授权,禁止复制转载。【本文首发于唐霜的博客】16;id’ => 5【版权所有】唐霜 www.tangshuang.net【作者:唐霜】,’parent_id转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。217; => 0,…【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。) // 内部结果
【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【未经授权禁止转载】【作者:唐霜】ng.net转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ng.net
而当执行往下执行,碰到array(著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】216;id’ => 【本文首发于唐霜的博客】【本文受版权保护】12,’parent_id&【本文受版权保护】本文作者:唐霜,转载请注明出处。#8217; => 5,̷【原创不易,请尊重版权】原创内容,盗版必究。0;)时,发生了:
【关注微信公众号:wwwtangshua【未经授权禁止转载】【原创内容,转载请注明出处】ngnet】【版权所有】唐霜 www.tangshu本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】ang.net【访问 www.tangshuang.n【本文首发于唐霜的博客】【未经授权禁止转载】et 获取更多精彩内容】【转载请注明来源】【本文受版权保护】著作权归作者所有,禁止商业用途转载。[2]=> array(̵转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】6;id’ => 12【原创不易,请尊重版权】【本文受版权保护】,’parent_id未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net217; => 5,…本文作者:唐霜,转载请注明出处。【本文受版权保护】)
【作者:唐霜】【本文首发于唐霜的博客】转载请注明出处:www.tangshua转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。ng.net【原创内容,转载请注明出处】$tmp[5][‘child著作权归作者所有,禁止商业用途转载。【转载请注明来源】ren’][0] = arr原创内容,盗版必究。【未经授权禁止转载】ay(‘id’ 【转载请注明来源】【原创不易,请尊重版权】=> 12,’pare【版权所有,侵权必究】原创内容,盗版必究。nt_id’ => 5本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。,…) // ①
【访问 www.tangshuang.n【作者:唐霜】【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】【本文受版权保护】由于&引用的关系,所以实际上
未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。$result[0][‘childrenR著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net17;][0] = array(R【作者:唐霜】【作者:唐霜】16;id’ => 1【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net2,’parent_id【本文受版权保护】【本文受版权保护】8217; => 5,…【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】;) // 内部结果
【本文首发于唐霜的博客】原创内容,盗版必究。
这个时候$temp[5]是一个已经包含c【版权所有,侵权必究】未经授权,禁止复制转载。hildren子元素的二维数组,如果往下本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。执行遇到array(‘id&转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】#8217; => 23,R转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。17;parent_id’ 【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。=> 12,…)时,你本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。就会发现
【本文首发于唐霜的博客】【访问 www.tangshuang.n【未经授权禁止转载】转载请注明出处:www.tangshuang.netet 获取更多精彩内容】【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。[5]=> array(̵本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。6;id’ => 23著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。,’parent_id转载请注明出处:www.tangshuang.net【未经授权禁止转载】217; => 12,…【原创内容,转载请注明出处】【转载请注明来源】;)
【版权所有,侵权必究】未经授权,禁止复制转载。$tmp[12][‘chil未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。dren’][0] = ar著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】ray(‘id’【未经授权禁止转载】【版权所有,侵权必究】 => 23,’par【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】ent_id’ => 本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。12,…)
【本文受版权保护】【访问 www.tangshuang.n原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】et 获取更多精彩内容】【转载请注明来源】$result[?][‘children【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net217;][0] = array(原创内容,盗版必究。【本文受版权保护】216;id’ => 著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。23,’parent_id&转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。#8217; => 12,R【版权所有,侵权必究】原创内容,盗版必究。30;) // 我们以为会发生的结果,其【转载请注明来源】【版权所有】唐霜 www.tangshuang.net实并没有发生
【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。
因为没有找到一个$tmp[12] = &原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】amp; $result[?],也就是说【原创内容,转载请注明出处】【转载请注明来源】没有一个与$tmp[12]对应的引用,$【转载请注明来源】本文版权归作者所有,未经授权不得转载。tmp[12]的变化不会引起其他任何值的【版权所有】唐霜 www.tangshuang.net【作者:唐霜】变化,$tmp[12]这个家伙会在返回值【未经授权禁止转载】【版权所有,侵权必究】中丢失(因为返回值是$result)。
原创内容,盗版必究。【作者:唐霜】【转载请注明来源】未经授权,禁止复制转载。而$tmp[$id] = &$tm【作者:唐霜】【原创内容,转载请注明出处】p[$parent_id][‘【转载请注明来源】【版权所有】唐霜 www.tangshuang.net;children’][$i未经授权,禁止复制转载。【作者:唐霜】];这一句起到了关键性作用。加上这一句之后,转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。我们再来跑一遍array(‘未经授权,禁止复制转载。原创内容,盗版必究。id’ => 23,&本文版权归作者所有,未经授权不得转载。【本文受版权保护】#8217;parent_id̵【作者:唐霜】【本文首发于唐霜的博客】7; => 12,…)未经授权,禁止复制转载。【本文首发于唐霜的博客】这个元素。
未经授权,禁止复制转载。【本文受版权保护】未经授权,禁止复制转载。【版权所有,侵权必究】转载请注明出处:www.tangshua本文作者:唐霜,转载请注明出处。原创内容,盗版必究。ng.net【版权所有,侵权必究】[2]=> array(̵【本文受版权保护】转载请注明出处:www.tangshuang.net6;id’ => 12【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net,’parent_id【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net217; => 5,…转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net)
著作权归作者所有,禁止商业用途转载。【作者:唐霜】$tmp[5][‘child原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。ren’][0] = arr【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。ay(‘id’ 【作者:唐霜】转载请注明出处:www.tangshuang.net=> 12,’pare【版权所有】唐霜 www.tangshuang.net【本文受版权保护】nt_id’ => 5【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】,…) // 重新从①开始【转载请注明来源】【转载请注明来源】演示
本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。$result[0][‘childrenR【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。17;][0] = array(‘id̵本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。7; => 12,’p【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】arent_id’ =>【作者:唐霜】【版权所有】唐霜 www.tangshuang.net; 5,…) // 内部结果
【访问 www.tangshuang.n【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.netet 获取更多精彩内容】【转载请注明来源】【未经授权禁止转载】未经授权,禁止复制转载。$tmp[12] = &$tmp【原创不易,请尊重版权】【本文受版权保护】[5][‘children&本文作者:唐霜,转载请注明出处。【转载请注明来源】#8217;][0] // 第二个&a本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。mp;出现了
【原创不易,请尊重版权】未经授权,禁止复制转载。【转载请注明来源】原创内容,盗版必究。[5]=> array(̵【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】6;id’ => 23【未经授权禁止转载】本文作者:唐霜,转载请注明出处。,’parent_id转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。217; => 12,…未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。;)
著作权归作者所有,禁止商业用途转载。【未经授权禁止转载】$tmp[12][‘chil【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】dren’][0] = ar本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。ray(‘id’未经授权,禁止复制转载。【作者:唐霜】 => 23,’par【版权所有,侵权必究】原创内容,盗版必究。ent_id’ => 【转载请注明来源】【关注微信公众号:wwwtangshuangnet】12,…)
本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。由于第二个&引用的原因,实际上发【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net生了:
转载请注明出处:www.tangshua未经授权,禁止复制转载。【本文受版权保护】ng.net【版权所有】唐霜 www.tangshu【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】ang.net【转载请注明来源】著作权归作者所有,禁止商业用途转载。$tmp[5][‘child【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】ren’][0][‘childrenR未经授权,禁止复制转载。【本文首发于唐霜的博客】17;][0] = array(R【原创内容,转载请注明出处】【本文受版权保护】16;id’ => 2【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。3,’parent_id本文作者:唐霜,转载请注明出处。【转载请注明来源】8217; => 12,̷【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】0;) // 内部结果
著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.n【转载请注明来源】【版权所有】唐霜 www.tangshuang.netet 获取更多精彩内容】【版权所有】唐霜 www.tangshu【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。ang.net【版权所有,侵权必究】$result[0][‘childrenR【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。17;][0][‘child【版权所有,侵权必究】【本文首发于唐霜的博客】ren’][0] = arr【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.netay(‘id’ 【转载请注明来源】未经授权,禁止复制转载。=> 23,’pare【原创不易,请尊重版权】【本文首发于唐霜的博客】nt_id’ => 1【本文受版权保护】【本文受版权保护】2,…) // 内部结果
【本文受版权保护】转载请注明出处:www.tangshua【原创不易,请尊重版权】【作者:唐霜】ng.net转载请注明出处:www.tangshua【本文受版权保护】【关注微信公众号:wwwtangshuangnet】ng.net
这个时候你可能已经看出了端倪。父子关系变著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。成了 5 > 12 > 23【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】,而这组关系,全部存储在了id=5的这个未经授权,禁止复制转载。【本文首发于唐霜的博客】顶级元素中,以多重的children元素【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。实现了父子孙结构。
【关注微信公众号:wwwtangshua【原创不易,请尊重版权】【原创内容,转载请注明出处】ngnet】著作权归作者所有,禁止商业用途转载。如此循环往复,你就会发现,无论你的父子关【作者:唐霜】转载请注明出处:www.tangshuang.net系多深,这个函数都能准确的构建对应的父子著作权归作者所有,禁止商业用途转载。【作者:唐霜】关系,最终形成树形结构存储在$resul【本文受版权保护】【版权所有,侵权必究】t中,将其返回。
本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.n转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。et 获取更多精彩内容】【本文受版权保护】该算法有一个问题,就是要求原始数组中,p本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。arent_id必须出现在该元素之前,否【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】则将导致该元素无法加入到某个元素的chi【原创内容,转载请注明出处】【转载请注明来源】ldren中去。
本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshua【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。ng.net2015-11-16 6981


