【问题标题】:Create a JSON tree view in PHP using delimiter使用分隔符在 PHP 中创建 JSON 树视图
【发布时间】:2021-11-23 14:50:38
【问题描述】:

我正在尝试为我正在尝试的项目创建一个文件浏览器类型树视图 JSON 以供 FancyTree 读取。

文件存储在数据库中,带有 ID、名称、URL、类型和代码字段。模拟数据库如下所示:

ID      name        URL.        Type            code
1       test        dir.dir1    txt             sometext
2       next        dir.dir1    txt             somemoretext
3       main        dir         txt            evenmoretext

我需要根据这些数据构建 JSON 树视图,使用 URL 作为路径(句点作为分隔符)并且文件位于最终目录中,因此树看起来像

/dir/dir1/test.txt
/dir/dir1/next.txt
/dir/main.txt

FancyTree JSON 输出应如下所示

[
    {
        "title": "dir",
        "folder": true,
        "children": [
            {
                "title": "dir1",
                "folder": true,
                "children": [
                    {
                        "title": "test.txt",
                        "key": 1
                    }, {
                        "title": "next.txt",
                        "key": 2
                    }
                ]
            }, {
                "title": "main.txt",
                "key": 3
            }
        ]
    }
]

目前,我正在将数据库中的数据放入 $scriptArray

SELECT 'name','url','type','id' FROM.....

然后我用

排序并构建一棵树
    $url = array_column($scriptArray, 'url');
    array_multisort($url, SORT_ASC, $scriptArray);

    $result = [];

    foreach($scriptArray as $item) {
        $loop = 0;
        $keys = array_reverse(explode('.', $item->url));
        $tmp = $item->name;
        $tmp2 = $item->type;

        foreach ($keys as $keyid => $key) {
            if($loop == 0) {
                $tmp = ["title" => $tmp.".".$tmp2, 'key' => $item->id];
            } else {
                $tmp = ["title" => $keys[$keyid - 1], "folder" => true, "children" => [$tmp]];
            }
            $loop++;
        }
        $tmp = ["title" => $keys[count($keys)-1], "folder" => true, "children" => [$tmp]];

        $result[] = $tmp;
    }

但是,我得到的输出是。

[
    {
        "title": "dir",
        "folder": true,
        "children": [
            {
                "title": "dir2",
                "folder": true,
                "children": [
                    {
                        "title": "test.txt",
                        "key": 1
                    }
                ]
            }
        ]
    },
    {
        "title": "dir",
        "folder": true,
        "children": [
            {
                "title": "dir2",
                "folder": true,
                "children": [
                    {
                        "title": "next.txt",
                        "key": 2
                    }
                ]
            }
        ]
    },
    {
        "title": "main.txt",
        "key": 3
    }
]

我尝试过应用 array_merge、array_merge_recursive 和其他各种方法,但均未成功。有人可以帮忙吗?

【问题讨论】:

  • 您是否尝试将 next.txt 和 test.txt 放入 'dir2' 分支,尽管它们具有不同的 url?
  • 对不起,没有。我已经更正了这个问题。显然,如果我确实有 /dir/dir2 甚至 /dir/dir1/dir2,那么该文件将出现在该树中。
  • 这与 JSON 无关,而是与您如何处理内存中的数据有关。你开始的阵列是什么?最后的数组是什么?把两者都用 PHP 表示法写下来。然后,编写循环以将一个转换为另一个。如果您遇到困难,请使用调试器单步执行代码,以找出它开始出现异常行为的地方。此外,请确保您有单元测试,复杂的转换更容易通过坚实的测试基础进行开发。

标签: php json delimiter fancytree


【解决方案1】:

除非您事先知道文件夹层次结构的最大深度,否则使用循环将不起作用。

更好的解决方案是“递归”构建文件夹路径,并将文件附加到最终文件夹。

这可以通过使用& 操作符创建一个引用来实现,并导航到它的子节点直到整个路径构建完成:

$result = array();
foreach($files as $file)
{
    // build the directory path if needed
    $directories = explode('.', $file->url); // get hierarchy of directories
    $currentRoot = &$result ; // set the pointer to the root directory per default
    foreach($directories as $directory)
    {
        // check if directory already exists in the hierarchy
        $dir = null ;
        foreach($currentRoot as $i => $d)
        {
            if(isset($d['folder']) && $d['folder'] and $d['title'] == $directory)
            {
                $dir = &$currentRoot[$i] ;
                break ;
            }
        }
        
        // create directory if missing
        if(is_null($dir))
        {
            $item =  array(
                'title' => $directory,
                'folder' => true,
                'children' => array()
            );
            $currentRoot[] = $item ;
            $dir = &$currentRoot[count($currentRoot)-1];
        }
        
        // move to the next level
        $currentRoot = &$dir['children'] ; 
        unset($dir);
    }
    
    // finally append the file in the latest directory
    $currentRoot[] = array(
        'title' => $file->name . '.' . $file->type,
        'key' => $file->id,
    );
    
    
    unset($currentRoot);
}

echo json_encode($result);

【讨论】:

  • 这非常有效。在检查目录是否存在时,我必须添加一个 isset($d['folder']),否则在检查没有文件夹属性的文件时会引发异常。我已将编辑添加为建议。
  • @AndyStubbs:我的 PHP 可能没有你的那么严格。我批准修改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多