MySQL/PHP 将树层次结构呈现为 array/JSON

MySQL/PHP rendering of tree hierarchy to array/JSON

给定以下层次结构的文件夹保存到数据库 table:

         top-
            |- subtop1
            |- subtop2
               |- subsubtop1

查询returns:


      ID NAME      PARENT ID
      1, top,       null
      2, subtop1,      1
      3, subtop2,      1
      4, subsubtop1,   3

我想将其转换为数组,然后转换为 JSON,如下所示:

      {
          "folder":
          {
                "fold_id": 1, "fold_name": "top", "fold_parent_fold_id": null,
                "sub_folders":
                {
                      "folder":
                      {
                            "fold_id": 2, "fold_name": "subtop1", "fold_parent_fold_id": 1,
                            "sub_folders": {}
                       },
                      "folder":
                      {
                            "fold_id": 3, "fold_name": "subtop2", "fold_parent_fold_id": 1,
                            "sub_folders":
                            {
                                  "folder":
                                  {
                                        "fold_id": 4, "fold_name": "subsubtop1", "fold_parent_fold_id": 3,
                                        "sub_folders":
                                        {
                                        }
                                  }
                            }
                       }
                }
          }
      }

这是我的代码(class 的一部分):

    public function buildTree ( $tree, $dir ) : array
    {
        $retarr = array();
        foreach ($tree as $tnode)
        {
        var_dump($tnode);
            if ( $tnode['folder']['fold_id'] == $dir['fold_parent_fold_id'])
            {
                if ( count($tnode['folder']['fold_id']['subfolders']) == 0 )
                {
                    // Next line errors with " Cannot use a scalar value as an array "
                    $tnode['folder']['fold_id']['subfolders'] =  array($dir['fold_id']=>$dir);
                }
                else
                {
                    array_push($tnode['folder']['fold_id']['subfolders'], array($dir['fold_id']=>$dir)  );
                }
            }
            else
            {
               $tnode = $this->buildTree ($tnode, $dir);
            }
        var_dump($tnode);
            array_push($retarr, $tnode);
        }
        return ($retarr);
    }

这是从数据库中获取平面层次列表并调用buildTree函数一点一点构建树数组的函数:


    public function getFolderTree ( $foldID ) : array
    {
        $foldContent = "";

        $sql =<<<SQL

        SELECT  1 oby,
                fold_id,
                fold_name,
                fold_parent_fold_id
        FROM    (SELECT * FROM folders
                 ORDER BY fold_parent_fold_id, fold_id) items_sorted,
                (SELECT @iv := ?) initialisation
        WHERE   find_in_set(fold_parent_fold_id, @iv)
        AND     length(@iv := concat(@iv, ',', fold_id))
        UNION
        SELECT  0 oby,
                fold_id,
                fold_name,
                fold_parent_fold_id
        FROM    folders
        WHERE   fold_id = ?
        ORDER BY 1, 4, 3
SQL;

        $rows = $this->db->query($sql, $foldID, $foldID)->fetchAll();
        $tree_array = array();
        $dirs = array();

        foreach ($rows as $row)
        {
            $subs = array();
            //var_dump ( $row );
            if ( $row['fold_parent_fold_id'] == null || count($dirs) == 0 )
            {
                $dirs[$row['fold_id']] = array ( "folder" => $row, "subfolders" => $subs );
                $tree_array = $dirs;
            }
            else
            {
               $tree_array = $this->buildTree ($tree_array, $row);
            }
            var_dump ( $tree_array );
        }
        //var_dump($rows);
        return ( json_encode($tree_array) );
    }

如上所述,我在 buildTree 函数中出现错误 运行:

                    // Next line errors with " Cannot use a scalar value as an array "
                    $tnode['folder']['fold_id']['subfolders'] =  array($dir['fold_id']=>$dir);

但是,我也不确定我的处理方式是否正确。我尝试使用数据库中的查询将数据提取为 JSON,但这没有用。

看看原生的php函数json_encode()

https://www.php.net/manual/en/function.json-encode.php

It is an inbuild php function that is used to convert PHP array or object into JSON (JavaScript Object Notation) representation.

一种方法是利用 OPP 结合标准方法构建 custom List。 为了不使用任何 sql-queries 中介 data-structure 用于保存初始关联。还假设此关联是 properly-set 和非循环的。

//for initial storage and to avoid db-query(but here can be adjusted even with sql)
class MyList
{
    public $arr=array();

    public function addNode($node)
    {
       $this->arr[$node->id]=$node;
    }
    
    public function getChilldren($pid)
    {
        $list=array();
        foreach($this->arr as $node)
        {
            if($node->pid==$pid)
            {
                $list[]=$node;
            }
        }
        return $list;
    }
}

//base component
class Node
{
    public $id;
    public $name;
    public $pid;
    public function __construct($id,$value,$pid)
    {
        $this->id=$id;
        $this->name=$value;
        $this->pid=$pid;
    }
    public function __toString()
    {
        return $this->id.":".$this->name.":".$this->pid;
    }
}

//list implementation
class MyNode
{
  public $root;
  public $leafs=array();
  public function __construct($root)
  {
      $this->root = $root;
  }
  public function add(MyList $list, $pid)
  {
      if($list->arr[$pid]!=null)
      {
          $this->root = $list->arr[$pid];
          $this->leafs=array();
      }
      else
      {
          return null;
      }
      $data = array();
      $data[]=$this->root;
      
      $current = array_shift($data);
      while($current  !=null)
      {
          //echo $current."<br>";
          $children=$list->getChilldren($current->id);
          foreach($children as $child)
          {
              $data[]=$child;
              $parentList = [$this];
              $start = null;
              while($parentList != null)
              {
                  $start = array_shift($parentList);
                  if($start->root->id == $child->pid)
                  {
                      $start->leafs[] = new MyNode($child);
                      //end_loop
                      break;
                  }
                  
                  //next search through children
                  foreach($start->leafs as $next)
                  {
                      $parentList[] = $next;
                  }
              }    
          }
          $current = array_shift($data);
      }
     // var_dump($this);
  }
}

//run
//add associations
$arr = new MyList();
$arr->addNode(new Node(4,"n4",3));
$arr->addNode(new Node(5,"n4",4));
$arr->addNode(new Node(6,"n4",4));
$arr->addNode(new Node(7,"n4",4));
$arr->addNode(new Node(1,"n1",null));
$arr->addNode(new Node(2,"n2",1));
$arr->addNode(new Node(3,"n3",1));
//names have no importance when constructing the tree

var_dump($arr);

//make full-list
$run = new MyNode(null);
$run->add($arr,1);

echo "<pre>";
print_r($run);
echo "</pre>";

echo json_encode($run)."<br>";

//make partial-list from a subtree
$run2= new MyNode(null);
$run2->add($arr,4);
echo json_encode($run2)."<br>";

输出:

//run1-json
{
"root":{"id":1,"name":"n1","pid":null},
"leafs":[{"root":{"id":2,"name":"n2","pid":1},"leafs":[]},
         {"root":{"id":3,"name":"n3","pid":1},
          "leafs":[{"root":{"id":4,"name":"n4","pid":3},
                    "leafs":[{"root":{"id":5,"name":"n4","pid":4},"leafs":[]},
                             {"root":{"id":6,"name":"n4","pid":4},"leafs":[]},
                             {"root":{"id":7,"name":"n4","pid":4},"leafs":[]}]}]}]
}

//run1-array
MyNode Object
(
    [root] => Node Object
        (
            [id] => 1
            [name] => n1
            [pid] => 
        )

    [leafs] => Array
        (
            [0] => MyNode Object
                (
                    [root] => Node Object
                        (
                            [id] => 2
                            [name] => n2
                            [pid] => 1
                        )

                    [leafs] => Array
                        (
                        )

                )

            [1] => MyNode Object
                (
                    [root] => Node Object
                        (
                            [id] => 3
                            [name] => n3
                            [pid] => 1
                        )

                    [leafs] => Array
                        (
                            [0] => MyNode Object
                                (
                                    [root] => Node Object
                                        (
                                            [id] => 4
                                            [name] => n4
                                            [pid] => 3
                                        )

                                    [leafs] => Array
                                        (
                                            [0] => MyNode Object
                                                (
                                                    [root] => Node Object
                                                        (
                                                            [id] => 5
                                                            [name] => n4
                                                            [pid] => 4
                                                        )

                                                    [leafs] => Array
                                                        (
                                                        )

                                                )

                                            [1] => MyNode Object
                                                (
                                                    [root] => Node Object
                                                        (
                                                            [id] => 6
                                                            [name] => n4
                                                            [pid] => 4
                                                        )

                                                    [leafs] => Array
                                                        (
                                                        )

                                                )

                                            [2] => MyNode Object
                                                (
                                                    [root] => Node Object
                                                        (
                                                            [id] => 7
                                                            [name] => n4
                                                            [pid] => 4
                                                        )

                                                    [leafs] => Array
                                                        (
                                                        )

                                                )

                                        )

                                )

                        )

                )

        )

)

//run2-json
{"root":{"id":4,"name":"n4","pid":3},
 "leafs":[
            {"root":{"id":5,"name":"n4","pid":4},"leafs":[]},
            {"root":{"id":6,"name":"n4","pid":4},"leafs":[]},
            {"root":{"id":7,"name":"n4","pid":4},"leafs":[]}]}