Mary
Mary

Reputation: 1

PHP - create a JSON object with multiple arrays

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);

Upvotes: 0

Views: 133

Answers (3)

Ravenous
Ravenous

Reputation: 1160

^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);

Upvotes: 2

Jeroen van der Laan
Jeroen van der Laan

Reputation: 724

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);

Upvotes: 1

Nigel Ren
Nigel Ren

Reputation: 57121

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)];

Upvotes: 1

Related Questions