WorkFlow
WorkFlow

Reputation: 23

PHP - Create multidimensional recursive array from string (Files/folders structure)

Someone asked same question 10 years ago but there is no answer to that

Reference: Trying to create Array from String (file/folder structure)


Update Jan 8, 2022: This is how array and tree should look like:

https://3v4l.org/6ULBZ#v8.1.1

The SQL output should be formed into this array structure from a string.

[
'id' => $key //Increment from foreach loop,
'file' => $row['name'] //Name of folders and files
'parent_id' => 0 // 0 - if no subfolder, $id if there is subfolder
]

I want to return a tree-level multidimensional array from file list stored in database as a string.

For example I store my work related path in database like this:

SELECT name FROM files;

... SQL Output

2021/Dec/File1.doc
2021/Dec/File2.doc
2021/Dec/File3.doc
2021/Nov/File1.doc
2021/Nov/File2.doc
2021/Nov/File3.doc
2021/Nov/File4.doc
2020/Jan/File1.doc
2020/Jan/File2.doc
2020/Jan/File3.doc

... PHP recursive array output should be categorized by folders, subfolders, more subfolders if exists and files on end.

-2021
--Dec
---File1.doc
---File2.doc
---File3.doc
--Nov
---File1.doc
---File2.doc
---File3.doc
---File4.doc
-2020
--Jan
---File1.doc
---File2.doc
---File3.doc

What would be the best way to achieve this performance wise?

What I got so far...

$files = [];
foreach ($sql as $row)
{
    // Separate directories
    $separator = explode('/', $row['name']); 
    /* Output:
    Array
    (
    [0] => 2021
    [1] => Dec
    [2] => file1.doc
    )
    */

    // Find the file via regex
    if (preg_match('/[^\/]*\.(doc|txt)/', $row['name'], $o))
    {
        $row['name'] = $o[0]; //Output: file1.doc
    }
    $files[] = $row;
}

... For now I only have a file names, now I need directories as well and then make a multidimensional array from it.

Upvotes: 1

Views: 190

Answers (2)

g4li
g4li

Reputation: 500

$files = [];
foreach ($sql as $row)
{
    // Separate directories
    $separator = explode('/', $row['name']); 
    /* Output:
    Array
    (
    [0] => 2021
    [1] => Dec
    [2] => file1.doc
    )
    */

    if (preg_match('/[^\/]*\.(doc|txt)/', $row['name']))
    {
        $node = &$files;
        while (count($separator) > 1) {
            $folder = array_shift($separator);
            if (!array_key_exists($folder, $node)) {
                $node[$folder] = [];
            }
            $node = &$node[$folder];
        }
        $node[] = $separator[0];
    }
}

Upvotes: 1

rocky gupta
rocky gupta

Reputation: 31

I have one solution for you, I hope this will help.

$files="2021/Dec/File1.doc, 
2021/Dec/File2.doc,
2021/Dec/File3.doc,
2021/Nov/File1.doc,
2021/Nov/File2.doc,
2021/Nov/File3.doc,
2021/Nov/File4.doc,
2020/Jan/File1.doc,
2020/Jan/File2.doc,
2020/Jan/File3.doc";

$files=explode(',',$files);

foreach($files as $file)
{
    $i=1;
    $paths=explode('/',$file);
    foreach($paths as $path)
    {
        for($j=0;$j<$i;++$j){
            echo '-';
        }
        echo $path;
        echo "<br/>";
        ++$i;
    }
    $i=0;
}

You can use your database files. by removing my files constant value and use your.

Upvotes: 0

Related Questions