Display tree menu of selected parent

2019-02-20 22:33发布

问题:

Here im building a tree menu. A category is accessed by its id and its child displayed. my function works fine for two level menu but fails to generate level third. Third level menu should be displayed only if id of a second level item clicked. I need this function to track the path to node too. That if a third level id is given than tree should be expanded to third level. i.e. parent of the child and if that parent has a parent too. mySQL Table

+-------+-----------+------------+
|  id   |  title    | parent_id  |
+-------+-----------+------------+
|   1   | Computers |    NULL    |
+-------+-----------+------------+
|   2   | Dell      |     1      |
+-------+-----------+------------+
|   3   | Laptops   |     2      |
+-------+-----------+------------+
|   4   | Desktops  |     2      |
+-------+-----------+------------+
|   5   | HP        |     1      |
+-------+-----------+------------+

PHP code

<?php
 $sql = "SELECT * FROM category";
 $statement= $db->prepare($sql);
 $statement->execute();
 $categories = array();
 $rootCategories = array();
 while ( $row = $statement->fetchObject() ) {
        $row->childs = array();
        $categories[$row->id] = $row;
        if(empty($row->parent_id)) {
                $rootCategories[$row->id] = $categories[$row->id];
        } else {
                $categories[$row->parent_id]->childs[] = $categories[$row->id];
        }
 }

  function rederTreeById($records, $id=false) {
        echo '<ul>';
        foreach($records as $record) {
                if($id == $record->id) {
                        echo '<li>'.$record->title;
                        if(!empty($record->childs)) {
                                rederTreeById($record->childs);
                        }
                        echo '</li>';
                } else {
                        echo '<li>'.$record->title.'</li>';
                }
        }
        echo '</ul>';
 }


 rederTreeById($rootCategories, 1);
?>

For example if clicked Computers then

  • Computer
    • Dell
    • HP

if Dell s clicked then

  • Computer
    • Dell
      • Laptops
      • Desktops
    • HP

回答1:

I see one problem with your solution. When you check for ID if($id == $record->id) you will only match the current level in the tree. i.e. selecting Dell with id=2 will not match the first iteration so your function wil not traverse to next level.

You need to keep track of the path to your selected menu.

In your case. When you select Dell you will only se "Computer", am I right?

How about something like this:

...
  function rederTreeById($records, $path) {
        echo '<ul>';
        foreach($records as $record) {
                if(in_array($record->id, $path)) {
                        echo '<li>'.$record->title;
                        if(!empty($record->childs)) {
                                rederTreeById($record->childs, $path);
                        }
                        echo '</li>';
                } else {
                        echo '<li>'.$record->title.'</li>';
                }
        }
        echo '</ul>';
 }

 function getPath($id) {
    $path = array();
    $current=$id;
    $path[] = 1
    while(!is_null($categories[$current]->parent_id)) {
        $current=$categories[$current]->parent_id
        $path[] = $current;
    }
    return $path;
 }


$selectedId = 1;


 rederTreeById($rootCategories, getPath($selectedId));
...