Home > Mobile >  PHP - Split string and form it as an array with parent child relation
PHP - Split string and form it as an array with parent child relation

Time:01-09

I AM ALMOST THERE PLEASE HELP IF YOU CAN

Lets say that I have multiple strings of files directory and files...

$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';

// Make it as an array
$files = explode(',', $files);

...First I want to split every file string and extract directories and file

$data = [];
foreach($files as $key => $file)
{
    $separator = explode('/', $file); // Output: [0 => '2021', 1 => 'Dec', 2 => 'File1.doc'];
    
    $file_name = end($separator); // Get file name as last element
    array_pop($separator); // Remove file name from array
    
    $files = [];
    
    $files[] = [
        'name' => $file_name,
        'folder' => $separator,
        ];
    $node = [];
    
    foreach ($files as $row)
    {
        $node['id'] = $key;
        // This is main folder (root)
        if (empty($row['folder']))
        {
            $node['file'] = $row['name'];
            $node['parent_id'] = 0;
        }
        else
        {
            // THIS IS PROBLEMATIC HOW TO NOW GET PARENT ID AND FOLDER NAME
            foreach ($row['folder'] as $fkey => $frow)
            {
                // I NEED HERE A PARENT_ID FROM PREVIOUS CHILD AND FILE NAME OF CURRENT FOLDER
            }
        }
    }
    $data[] = $node;
}

... Now I need to get folder names and check if folder has subfolder and set parent_id = id of folder.

...How to produce this array structure from the foreach loop above?

[
    [
        'id' => 1,
        'file' => '2021',
        'parent_id' => 0, // Main folder (2021)
    ],
    [
        'id' => 2,
        'file' => 'Dec',
        'parent_id' => 1, // Child of 2021
    ],
    [
        'id' => 3,
        'file' => 'File1.doc',
        'parent_id' => 2, // Child of Dec
    ],
    [
        'id' => 4,
        'file' => 'File2.doc',
        'parent_id' => 2, // Child of Dec
    ],
    [
        'id' => 5,
        'file' => 'File3.doc',
        'parent_id' => 2, // Child of Dec
    ],
    [
        'id' => 6,
        'file' => 'Nov',
        'parent_id' => 1, // Child of 2021
    ],
    [
        'id' => 7,
        'file' => 'File1.doc',
        'parent_id' => 6, // Child of Nov
    ],
    [
        'id' => 8,
        'file' => 'File2.doc',
        'parent_id' => 6, // Child of Nov
    ],
    [
        'id' => 9,
        'file' => 'Fil3.doc',
        'parent_id' => 6, // Child of Nov
    ],
    [
        'id' => 10,
        'file' => 'File4.doc',
        'parent_id' => 6, // Child of Nov
    ],
    [
        'id' => 11,
        'file' => '2020',
        'parent_id' => 0, // Main folder (2020)
    ],
    [
        'id' => 12,
        'file' => 'Jan',
        'parent_id' => 11, // Child of 2020
    ],
    [
        'id' => 13,
        'file' => 'File1.doc',
        'parent_id' => 11, // Child of jan
    ],
    [
        'id' => 14,
        'file' => 'File2.doc',
        'parent_id' => 11, // Child of jan
    ],
    [
        'id' => 15,
        'file' => 'File3.doc',
        'parent_id' => 11, // Child of jan
    ],
];

Here is how final structure needs to looks like and how I plan to use recursive function to get tree-level array.

https://3v4l.org/6ULBZ

CodePudding user response:

I rewrote the code but this does the trick:

<?php

$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';

// Make it as an array
$files = explode(",\n", $files);

$out = [];
foreach ($files as $line) {
    [$year, $month, $file] = explode('/', $line);

    if (!$year_id = get_id($out, $year)) {
        $year_id = add_value($out, $year);
    }
    if (!$month_id = get_id($out, $month)) {
        $month_id = add_value($out, $month, $year_id);
    }
    add_value($out, $file, $month_id);
}

var_dump($out);

function add_value(&$out, $name, $parent_id = null)
{
    $last_id = end($out)['id'] ?? 0;
    $new_id = $last_id   1;

    array_push($out, [
        'id' => $new_id,
        'file' => $name,
        'parent_id' => $parent_id ?? 0,
    ]);

    return $new_id;
}

function get_id($out, $name)
{
    foreach ($out as $item) {
        if ($item['file'] == $name) {
            return $item['id'];
        }
    }

    return null;
}

->

[
    {
        "id": 1,
        "file": "2021",
        "parent_id": 0
    },
    {
        "id": 2,
        "file": "Dec",
        "parent_id": 1
    },
    {
        "id": 3,
        "file": "File1.doc",
        "parent_id": 2
    },
    {
        "id": 4,
        "file": "File2.doc",
        "parent_id": 2
    },
    {
        "id": 5,
        "file": "File3.doc",
        "parent_id": 2
    },
    {
        "id": 6,
        "file": "Nov",
        "parent_id": 1
    },
    {
        "id": 7,
        "file": "File1.doc",
        "parent_id": 6
    },
    {
        "id": 8,
        "file": "File2.doc",
        "parent_id": 6
    },
    {
        "id": 9,
        "file": "File3.doc",
        "parent_id": 6
    },
    {
        "id": 10,
        "file": "File4.doc",
        "parent_id": 6
    },
    {
        "id": 11,
        "file": "2020",
        "parent_id": 0
    },
    {
        "id": 12,
        "file": "Jan",
        "parent_id": 11
    },
    {
        "id": 13,
        "file": "File1.doc",
        "parent_id": 12
    },
    {
        "id": 14,
        "file": "File2.doc",
        "parent_id": 12
    },
    {
        "id": 15,
        "file": "File3.doc",
        "parent_id": 12
    }
]

CodePudding user response:

Hopefully this will give you required output after managing data in level wise hierarchy

<?php
$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';

// Make it as an array
$files = explode(',', $files);

$data = [];
$autoIncreamentId = 0;
$level = [];
$parent_ids = [];
foreach($files as $key => $file)
{
    $separator = explode('/', $file); // Output: [0 => '2021', 1 => 'Dec', 2 => 'File1.doc'];
    $node = [];

    foreach ($separator as $ind=>$row)
    {
        $row = trim($row);
        $isDir = 1;
        if (preg_match('/[^\/]*\.(doc|txt)/', $row, $o))
        {
            $isDir = 0;
        }
        //if directory already used then just pull id for child use
        if($isDir && isset($level[$ind.'_'.$row])){
            //maintain ids of the parent hirachy to use in child files
            $node[$ind] = array(
                'id'=>(int)$level[$ind.'_'.$row]
                 );
        }else{
            //add node using previous level id
            $autoIncreamentId  =1;
            $parent_id = (int)@$node[$ind-1]['id'];
            $node[$ind] = array(
                'id'=>$autoIncreamentId,
                'file'=> $row,
                'parent_id' => $parent_id
                 );
            //save level wise id to use in future
            $level[$ind.'_'.$row] = $autoIncreamentId;
        }
    }
    //add in data just node and ignore empty nodes
    foreach($node as $item){
        if(isset($item['file'])){
            $data[] = $item;
        }
    }
}

print_r(json_encode($data));
  •  Tags:  
  • Related