面包屑导航:网站中用于展示页面层级关系的导航栏,同时也可以清楚的告知用户它当前身处于哪个位置(层级),以确定网站的结构和增强用户浏览体验。

简单示例:

这里以php手册为例,展示一个简单的面包屑导航。

接下来就手动实现一下吧

测试数据

    const arr = [['id' => 1, 'pid' => 0, 'city' => '江西'],['id' => 2, 'pid' => 0, 'city' => '广东'],['id' => 3, 'pid' => 1, 'city' => '宜春'],['id' => 4, 'pid' => 3, 'city' => '丰城'],['id' => 5, 'pid' => 4, 'city' => '尚庄'],['id' => 6, 'pid' => 2, 'city' => '深圳'],['id' => 7, 'pid' => 6, 'city' => '翻身'],];

需求效果:

思路分析:

结合需求效果来分析测试数据可以看到最终要求的效果是从顶级名称一直延续到它的最下级子级名称。

    所以可以衍生出两种思路:

1.传入顶级id,得到它本身与它的n多子级,组成一个新的数组,循环拼接html展示。

顶级名称是江西,江西的id是1,所以根据  子级的pid = 父级的id ,找到它的子级;

遍历整个数组,pid是1的只有宜春,可以看到宜春的id是3,那么又得根据3来再次遍历整个数组,找到宜春的子级,也就是丰城;

再找到丰城的id,id为4,遍历整个数组pid为4的只有尚庄;

尚庄的id为5,再拿5去数组中寻找有没有pid为5的数据,此时可以看到没有了,那么整个流程结束。

接下来只需要将每次找到的子级数组追加到一个新数组中即可组成想要的数据。

整体思路下可以得知:拿到每次循环后找到的子级id当成它的子级的pid来传入,以此实现不断循环,也就是递归,不断调用自身,以达到最终效果。

2.传入最子级id,得到它本身与它的n多父级,组成一个新的数组,循环拼接html展示。

与思路一相反,思路一是根据父亲找与儿子的关系图,而思路二是根据儿子找与父亲的关系图。     

最子级名称是尚庄,尚庄的pid是4,所以根据  父级的id = 子级的pid,找到它的父级;

遍历整个数组,id是4的只有丰城,可以看到丰城的pid是3,那么又得根据pid为3来再次遍历整个数组,找到丰城的父级,也就是宜春;

再找到宜春的pid,pid为1,遍历整个数组pid为1的只有江西;

江西的pid为0,再拿0去数组中寻找有没有id为0的数据,此时可以看到没有了,那么整个流程结束。

接下来只需要将每次找到的子级数组追加到一个新数组中即可组成想要的数据。

整体思路下可以得知:拿到每次循环后找到的父级id当成它的子级的pid来传入,以此实现不断循环,也就是递归,不断调用自身,以达到最终效果。

代码实践:

 无论是思路一还是思路二,要实现递归,并把所有数据汇总到一个数组中,那么就得使用static或&array或global来存储每次遍历的值(不然这次拿到了想要的结果,下次往新数组里追加数据的时候,上次追加的数据就丢掉了),这里就以static(静态数组)和&array(传值引用)为例来实现吧。

思路一:

静态数组法(代码思路参照思路1的分析):

    /*** 无限分类之得到导航完整层级数组(传入顶级)* @param array $data* @param int $id 顶级id* @return array*/public function getFatherToLink(array $data, int $id): array{static $arr = [];  //声明静态空数组,存储每次遍历后得到的数据foreach ($data as $value) {//由于下列递归只会找子级,不会传入本身,所以当新数组为空且id为传入的id时就说明数据是其本身,需要将它追加到新数组中if (count($arr) == 0 && $value['id'] == $id) {$arr[] = $value;}//这里递归只会找子级if ($value['pid'] == $id) {$arr[] = $value; //将子级追加到新数组中$this->getFatherToLink($data, $value['id']);}}return $arr;}

传值引用法(代码思路参照思路1的分析):

/*** 无限分类之得到导航完整层级数组(传入顶级)* @param array $data* @param int $id 顶级id* @param array $arr* @return array*/public function getFatherToLinkAAA(array $data, int $id, &$arr = []): array{foreach ($data as $value) {//由于下列递归只会找子级,不会传入本身,所以当新数组为空且id为传入的id时就说明数据是其本身,需要将它追加到新数组中if (count($arr) == 0 && $value['id'] == $id) {$arr[] = $value;}//这里递归只会找子级if ($value['pid'] == $id) {$arr[] = $value;$this->getFatherToLinkAAA($data, $value['id'], $arr); //由于形参已经加了&,所以每次$arr的值将会保留继续使用(而不是清除)}}return $arr;}

思路二:

这里讲一下,为什么要反转数组。

根据代码思路来看,传入子级id为5,因为$arr[]=$value在递归触发之前调用,那么就会逐级向上寻找父类依次得到:

尚庄 ->  丰城  --> 宜春  -> 江西

但我们实际要的效果是:

江西  ->  宜春 --> 丰城  -> 尚庄

所以需要将最终的$arr数组,反转一下来得到正确的效果。

静态数组法(代码思路参照思路2的分析):

    /*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLinkAAA(array $data, int $id): array{static $arr = []; //声明静态空数组foreach ($data as $value) {//这里只会找父级if ($value['id'] == $id) {$arr[] = $value;$this->getSonToLinkAAA($data, $value['pid']);}}return array_reverse($arr);//array_reverse直接反转数组}

传值引用法(代码思路参照思路2的分析):

    /*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLink(array $data, int $id, array &$arr = []): array{foreach ($data as $value) {if ($value['id'] == $id) {$arr[] = $value;$this->getSonToLink($data, $value['pid'], $arr);}}krsort($arr); //不通过array_reverse也可以使用krsort根据键名排序 来反转数组return $arr;}

试验论证:

到了现在,我们知道可以有两种思路来实现效果,效果也是实现了的;但是这里的测试数据只有一个同级元素呀,没有干扰性,不足以论证思路正确性。那么现在往原始测试数据中再多追加几个同级元素来增强干扰性,再来测试这两种思路是否可以禁得住考验吧!

    //增强干扰性的测试数据const arr = [['id' => 1, 'pid' => 0, 'city' => '江西'],['id' => 2, 'pid' => 0, 'city' => '广东'],['id' => 3, 'pid' => 1, 'city' => '宜春'],['id' => 4, 'pid' => 3, 'city' => '丰城'],['id' => 5, 'pid' => 4, 'city' => '尚庄'],['id' => 6, 'pid' => 2, 'city' => '深圳'],['id' => 7, 'pid' => 6, 'city' => '翻身'],#以下是追加的同级元素数据,用来试验论证,也是增强干扰性['id' => 8, 'pid' => 1, 'city' => '南昌'],['id' => 9, 'pid' => 8, 'city' => '高新区'],];

思路一测试后的数据如下:

思路二测试后的数据如下:

好了,结果已经明了,显然思路一这种通过传入顶级id得到本身和子类的方式,

在数据具备同级元素的时候是不适用的,只适用于数据不具备同级元素的时候;

这局限性太大了,后台无限分类后的数据怎么,可能没有同级元素数据呢?

所以,思路1pass! 我们只能选取思路2来实现面包屑导航!

进阶讨论:

思路1被干掉了,合适的只有思路2。

仔细看思路2中,我们是借助array_reversekrsort反转了数组再返回最终值的。

实际上是可以直接通过遍历得到最终值,而不需要借助php函数再反转的,上述例子只是为了方便理解才这么写。

那么不借助php函数改怎么写呢?

我想你应该猜到了,那就是把

$arr[] = $value

写在递归之后调用,这样就会从最顶级开始自上而下往$arr里追加数据,而不是从传入的子级本身开始自下而上往$arr里追加数据。为了方便,传值引用和静态数组进阶版就直接放一起展示了。

/*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLinkAAABBB(array $data, int $id, array &$arr = []): array{foreach ($data as $value) {//这里只会找父级if ($value['id'] == $id) {//这里会一直找到最顶级$this->getSonToLinkAAABBB($data, $value['pid'], $arr);$arr[] = $value; //从最顶级开始插入数据,再跳出当前级别递归,往外级递归继续插入。}}return $arr;}/*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLinkAAACCC(array $data, int $id): array{static $arr = []; //声明静态空数组foreach ($data as $value) {//这里只会找父级if ($value['id'] == $id) {//这里会一直找到最顶级$this->getSonToLinkAAACCC($data, $value['pid']);$arr[] = $value; //从最顶级开始插入数据,再跳出当前级别递归,往外级递归继续插入。}}return $arr;}

最终效果:

<?php
/*** Created by phpStrom* User: Anbin* Date: 2022/8/26* Time: 16:37*//*** 无限分类之面包屑导航案例* Class Link*/
class Link
{//测试数据const arr = [['id' => 1, 'pid' => 0, 'city' => '江西'],['id' => 2, 'pid' => 0, 'city' => '广东'],['id' => 3, 'pid' => 1, 'city' => '宜春'],['id' => 4, 'pid' => 3, 'city' => '丰城'],['id' => 5, 'pid' => 4, 'city' => '尚庄'],['id' => 6, 'pid' => 2, 'city' => '深圳'],['id' => 7, 'pid' => 6, 'city' => '翻身'],#以下是追加的同级元素数据,用来试验论证,也是增强干扰性['id' => 8, 'pid' => 1, 'city' => '南昌'],['id' => 9, 'pid' => 8, 'city' => '高新区'],];//思路一/*** 无限分类之得到导航完整层级数组(传入父级)* @param array $data* @param int $id 父级id* @return array*/public function getFatherToLink(array $data, int $id): array{static $arr = [];foreach ($data as $value) {if (count($arr) == 0 && $value['id'] == $id) {$arr[] = $value;}if ($value['pid'] == $id) {$arr[] = $value;$this->getFatherToLink($data, $value['id']);}}return $arr;}/*** 无限分类之得到导航完整层级数组(传入顶级)* @param array $data* @param int $id 顶级id* @param array $arr* @return array*/public function getFatherToLinkAAA(array $data, int $id, &$arr = []): array{foreach ($data as $value) {//由于下列递归只会找子级,不会传入本身,所以当新数组为空且id为传入的id时就说明数据是其本身,需要将它追加到新数组中if (count($arr) == 0 && $value['id'] == $id) {$arr[] = $value;}//这里递归只会找子级if ($value['pid'] == $id) {$arr[] = $value;$this->getFatherToLinkAAA($data, $value['id'], $arr); //由于形参已经加了&,所以每次$arr的值将会保留继续使用(而不是清除)}}return $arr;}#################################################################################################################################//这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---#################################################################################################################################//思路二/*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLink(array $data, int $id, array &$arr = []): array{foreach ($data as $value) {if ($value['id'] == $id) {$arr[] = $value;$this->getSonToLink($data, $value['pid'], $arr);}}krsort($arr); //不通过array_reverse也可以使用krsort根据键名排序 来反转数组return $arr;}/*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLinkAAA(array $data, int $id): array{static $arr = []; //声明静态空数组foreach ($data as $value) {//这里只会找父级if ($value['id'] == $id) {$arr[] = $value;$this->getSonToLinkAAA($data, $value['pid']);}}return array_reverse($arr);//array_reverse直接反转数组}/*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLinkAAABBB(array $data, int $id, array &$arr = []): array{foreach ($data as $value) {//这里只会找父级if ($value['id'] == $id) {//这里会一直找到最顶级$this->getSonToLinkAAABBB($data, $value['pid'], $arr);$arr[] = $value; //从最顶级开始插入数据,再跳出当前级别递归,往外级递归继续插入。}}return $arr;}/*** 无限分类之得到导航完整层级数组(传入子级)* @param array $data* @param int $id 子级id* @param array $arr* @return array*/public function getSonToLinkAAACCC(array $data, int $id): array{static $arr = []; //声明静态空数组foreach ($data as $value) {//这里只会找父级if ($value['id'] == $id) {//这里会一直找到最顶级$this->getSonToLinkAAACCC($data, $value['pid']);$arr[] = $value; //从最顶级开始插入数据,再跳出当前级别递归,往外级递归继续插入。}}return $arr;}#################################################################################################################################//这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---这里是分割线---#################################################################################################################################/*** 将无限分类后的数组转换成导航html* @param array $data* @return string*/public function arrayToLink(array $data): string{$str = '';foreach ($data as $item) {//这里做个判断,当是最后一位则不需要拼接->$endString = $item == end($data) ? '' : '->&nbsp;&nbsp;';$str .= "<a href='' >" . $item['city'] . "</a>&nbsp;&nbsp;" . $endString;}return $str;}//真正调用查看效果方法public function link(){//思路一//$data = $this->getFatherToLink(self::arr, 1);//$data = $this->getFatherToLinkAAA(self::arr, 1);//思路二(反转数组版)//$data = $this->getSonToLink(self::arr, 5);//$data = $this->getSonToLinkAAA(self::arr, 5);//思路二(不需反转数组版)$data = $this->getSonToLinkAAABBB(self::arr, 5);$data = $this->getSonToLinkAAACCC(self::arr, 5);//返回最终效果htmlreturn $this->arrayToLink($data);}}

php无限分类之面包屑导航相关推荐

  1. java 面包屑导航_基于SpringBoot打造在线教育系统(7)-- 面包屑导航与子分类

    这一节我们来讲一下面包屑导航的问题. 先看思路,当我们点击左侧的一级课程,是不是可以拿到一个ID? 这个ID的作用可大了,我们有了这个ID,本意是通过它去寻找它所有的子节点. 看图,假设[JAVA基础 ...

  2. 一行代码搞定WordPress面包屑导航breadcrumb

    有好几位网友在问WordPress面包屑导航breadcrumb怎么操作,网上有些教程是去function文件中定义,其实不用那么复杂,很简单一行代码就能搞定.下面随ytkah一起来看看.如果是单页, ...

  3. 南山谷主:面包屑导航是什么意思?对SEO有何作用?

    面包屑导航是什么意思 面包屑导航(BreadcrumbNavigation)这个概念来自童话故事"汉赛尔和格莱特",当汉赛尔和格莱特穿过森林时,不小心迷路了,但是他们发现在沿途走过 ...

  4. 面包屑php源码,WordPress免插件实现面包屑导航的示例代码

    你如果在开发自己的wordpress主题,想加入面包屑导航,而又不想使用插件的话,下面的代码对你有帮助,这里提供了网上较为流行的两种代码,一是功能非常完善的,一是一个较为简洁的代码. 前面介绍了一种方 ...

  5. php面包屑导航实现思路,WordPress实现面包屑导航的方法

    面包屑导航是一个很基本的功能,当网站结构复杂的时候,面包屑导航可以不让用户迷失方向.WordPress实现面包屑导航无非是安装插件,或者直接写代码.在网上看了不少介绍,有些代码感觉质量不高,插件也有很 ...

  6. 什么是面包屑导航,它对SEO的影响有哪些?

    众所周知,面包屑导航设计思路来源于一则童话故事,在不小心迷失方向后,主人公利用沿途撒下的面包屑,顺利的找到回家的路,这就是面包屑导航的原型. 它几乎是所有优秀网站的重要组成部分,不仅可以让访客清晰的知 ...

  7. WordPress不可忽视的面包屑导航SEO优化技巧

    什么是网站面包屑导航?面包屑导航意在告知用户所处的当前网页的位置,方便用户可以通过该导航快速返回上一级网页. 面包屑导航一般都在导航的下面,形式一般为 首页 > 一级目录名称 > 二级目录 ...

  8. 面包屑导航:最佳做法和示例

    面包屑导航通常在设计和开发过程中被忽略. 有些人可能认为它是不必要的,而另一些人可能觉得它的价值太大了. 事实是,面包屑导航将显着提高网站的可用性. 面包屑为用户提供了另一种导航方法,使他们可以看到他 ...

  9. 面包屑导航:最佳实践和范例

    译文出处:http://www.cogu.cn/archives/65 本文翻译自:http://www.hongkiat.com/blog/breadcrumb-navigation-examine ...

最新文章

  1. ASP.NET Core WebAPI中的分析工具MiniProfiler
  2. SSM整合(2): spring 与 mybatis 整合
  3. CLEARTEXT communication to xxx not permitted by network security policy
  4. web 静态页面和动态页面的区别
  5. 莓良心(第二类斯特林数)
  6. 二进制法生成1-n的子集
  7. centos 安装oracle java,CentOS 4.4下安装Oracle 10
  8. linux系统取代windows,Linux不可能取代Windows
  9. python爬虫架构师之路_一位资深 架构师大牛给予Java技术提升的学习路线建议
  10. metasploit命令大全
  11. 阶段3 1.Mybatis_08.动态SQL_02.mybatis中动态sql语句-where标签的使用
  12. html5炫酷动画及源码,分享8个难忘的HTML5炫酷动画及源码
  13. APP测试基本流程以及APP测试要点
  14. poj 1838 Banana
  15. VC及esxi升级的必要性和步骤
  16. 使用 SCTP 优化网络
  17. 重聚焦显微镜原理和理解
  18. 补第十一次课作业(法律法规、标准规范、职业道德)
  19. Part1---3.数据库编程与完整性
  20. 阿里云 mysql 100_MySQL服务进程占用系统CPU达100%-阿里云开发者社区

热门文章

  1. 分享50个AI绘画prompt的关键词,让你的AI绘画更贴近想法
  2. 猎头术语:Delimited Search
  3. joomla自定义html,Joomla教程:为页面和模块添加独立的自定义Class
  4. oracle ebs mom,MOM制造运营管理系统
  5. 微信小程序渲染后端返回的图片
  6. 敬伟PS教程:新版PS变化篇D
  7. PIL之ImageFilter下的基本操作
  8. 如何实现在zoom会议时演讲ppt时 自己能看到注释而别人看不到
  9. python util_Python util.util方法代码示例
  10. 西交《生物化学》在线作业