0

I have a PHP function to create a directory tree and I cannot format the result to obtain a JSON file like this:

[
  {
    text: 'Parent',
    href: 'parent/',
    nodes: [
      {
        text: 'Child',
        href: 'child/',
        nodes: [
          {
            text: 'Grandchild',
            href: 'grandchild/',
          },
          {
            text: 'Grandchild',
            href: 'grandchild/',
          }
        ]
      },
      {
        text: 'Child',
        href: 'child/',
      }
    ]
  },
  {
    text: 'Parent',
    href: 'parent/',
  },
  {
    text: 'Parent',
    href: 'parent/',
  },
  {
    text: 'Parent',
    href: 'parent/',
  },
  {
    text: 'Parent',
    href: 'parent/',
  },
  {
    text: 'Parent',
    href: 'parent/',
    nodes: [
      {
        text: 'Child',
        href: 'child/',
        nodes: [
          {
            text: 'Grandchild',
            href: 'grandchild/',
          },
          {
            text: 'Grandchild',
            href: 'grandchild/',
          }
        ]
      },
      {
        text: 'Child',
        href: 'child/',
      }
    ]
  }
]

Here my PHP function, someone can help me? Thanks

function scandir_rec($root)
{
    $data = [];

    if (!is_dir($root)) {
        return;
    }

    $dirs = scandir($root);

    foreach ($dirs as $dir) {

        if ($dir == '.' || $dir == '..') {
            continue;
        }

        $path = $root . '/' . $dir;  

        $data[] = ['text'=>$dir, 'link'=>urlencode($path)];

        if (is_dir($path)) {

            $data[] = ['nodes' => scandir_rec($path)]; 

        }
    }

    return json_encode($data, JSON_UNESCAPED_SLASHES);
}

// init call
$rootDir = '/var/usr';

scandir_rec($rootDir);

3 Answers 3

2

^what those guys said.

<?php
function scandir_rec($root)
{
    $data = [];

    if (!is_dir($root)) {
        return;
    }

    $dirs = scandir($root);

    foreach ($dirs as $dir) {

        if ($dir == '.' || $dir == '..') {
            continue;
        }

        $path = $root . DIRECTORY_SEPARATOR . $dir;

        if (!is_dir($path)) continue;

        $chunk = ['text' => $dir, 'link' => urlencode($path)];

        $nodes = scandir_rec($path);
        if (!empty($nodes)) $chunk['nodes'] = $nodes;

        $data[] = $chunk;
    }

    return $data;
}

$rootDir = '/var/usr';

json_encode(scandir_rec($rootDir), JSON_UNESCAPED_SLASHES);
Sign up to request clarification or add additional context in comments.

7 Comments

Thank for uour help. I tried your code and I get empty nodes when a folder is empty, so I modified it "if (is_dir($path) && count(scandir($path)) !== 0)" but I still get an empty node and an extra array at the end of the JSON data. I've been scratching my head for 1 hour.
count(scandir($path)) will be 2 if directory is empty, due to . and ..
Yes you are right. however I always get an empty node and an additional array at the end. I will take the code from the beginning.
always the same problem, it even adds the files. it's strange.
Thought you wanted files. Add if (is_file($path)) continue; under $path = $root . DIRECTORY_SEPARATOR . $dir;
|
1

The main problem is that after each recursive call, you return the sub data as a json encoded string rather than the data hierarchy. You could change this to return the data and the caller would have to json encode the result.

Alternatively, when you do the recursive call, json_decode() the return value. So change the line...

$data[] = ['nodes' => scandir_rec($path)]; 

to

$data[] = ['nodes' => json_decode(scandir_rec($path), true)];

Comments

1

As mentioned in answer before, your are json encoding the result of each return value of scandir_rec, with the final encoded string ending up quite messy.

Another undesirable result occurs because of the line $data[] = ['nodes' => scandir_rec($path)];. Resulting in a data structure that does not resemble the structure of the JSON file you presented, but instead considers the entire result as an array instead of an object. I believe you might want to consider doing something like this:

function scandir_rec($root)
{
    if (!is_dir($root)) {
        return [];
    }

    $data = [];
    $data['text'] = $root;
    $data['href'] = urlencode($root);
    $nodes = [];

    $dirs = scandir($root);
    foreach ($dirs as $dir) {
        if ($dir === '.' || $dir === '..') {
            continue;
        }
        $path = $root . '/' . $dir;
        if (is_dir($path)) {
            $nodes[] = scandir_rec($path);
        }
    }
    if (false === empty($nodes)) {
        $data['nodes'] = $nodes;
    }
    return $data;
}

Which results in a matching structure of your example.

Edit:

To get the result that you want, you could then do something like:

$directory = __DIR__;
$result = scandir_rec($directory);
$data = json_encode($data);

3 Comments

In your example, nodes defaults to an empty array.
No, I meant the given JSON example does not feature the key nodes when the node has no children.
Thank for your help. I get an empty node and an extra array at the end of the JSON data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.