PHP实现查找菜单树中无子节点(非父节点)的最新记录
解决PHP中查找菜单树最新叶子节点的问题
我来帮你搞定这个需求!咱们用纯PHP循环和函数来实现,完全符合你的要求,不需要用递归或者复杂的SQL语句(当然如果用SQL也能查,但你指定了用PHP循环和函数,那咱们就走这条路线)。
核心思路
叶子节点的定义是没有子节点的节点,也就是这个节点的id不会出现在任何其他节点的parent_id字段里。然后要找“最新条目”,假设你的id是自增主键(通常菜单表都会这么设计),那id值最大的叶子节点就是最新创建的。
分步实现代码
首先咱们分三个函数来实现,逻辑清晰,也方便复用:
- 获取所有菜单数据:从数据库拉取完整的菜单列表
- 筛选所有叶子节点:通过循环判断找出所有没有子节点的节点
- 找出最新的叶子节点:对叶子节点按
id降序排序,取第一个就是最新的
// 假设你已经建立了PDO数据库连接,$pdo是你的连接实例 // 如果你用mysqli,只需要把查询部分改成mysqli的写法就行 function getAllMenuItems($pdo) { $stmt = $pdo->query("SELECT id, title, parent_id FROM menu"); // 把结果转成关联数组,方便后续操作 return $stmt->fetchAll(PDO::FETCH_ASSOC); } function getLeafNodes($menuItems) { $parentIds = []; // 第一步:先收集所有作为父节点的ID(也就是所有出现在parent_id里的有效ID) foreach ($menuItems as $item) { // 这里假设parent_id为0或null代表根节点,不需要计入父节点集合 if (!empty($item['parent_id'])) { $parentIds[] = $item['parent_id']; } } // 去重,避免重复判断,提升效率 $parentIds = array_unique($parentIds); $leafNodes = []; // 第二步:筛选叶子节点——ID不在父节点集合里的节点 foreach ($menuItems as $item) { if (!in_array($item['id'], $parentIds)) { $leafNodes[] = $item; } } return $leafNodes; } function getLatestLeafNode($leafNodes) { if (empty($leafNodes)) { return null; } // 按ID降序排序,ID最大的就是最新创建的节点 usort($leafNodes, function($a, $b) { return $b['id'] - $a['id']; }); // 返回第一个元素,也就是最新的叶子节点 return $leafNodes[0]; } // 调用示例 $menuItems = getAllMenuItems($pdo); $leafNodes = getLeafNodes($menuItems); $latestLeaf = getLatestLeafNode($leafNodes); // 输出结果 if ($latestLeaf) { echo "最新叶子节点:ID=" . $latestLeaf['id'] . ",标题=" . $latestLeaf['title']; } else { echo "没有找到任何叶子节点"; }
细节调整说明
- 如果你的菜单表中,根节点的
parent_id是null而不是0,只需要把getLeafNodes里的判断改成if ($item['parent_id'] !== null)就行。 - 如果“最新条目”的判断不是基于
id,而是有单独的created_at字段,那只需要修改排序逻辑,把$b['id'] - $a['id']改成strtotime($b['created_at']) - strtotime($a['created_at'])即可。 - 如果你需要的是所有叶子节点按最新排序,而不是只取第一个,直接返回排序后的
$leafNodes数组就行。
内容的提问来源于stack exchange,提问作者user381403
相关产品推荐
相关产品推荐

