1

I have a list of URL strings:

'page1',
'page1/url1',
'page1/url2/suburl1',
'page2/url3',
'page2/url4/suburl2',
'page2/url4/suburl3'

And I want to convert it to a nested URL according to their structure:

Array
(
    [page1] => Array
        (
            [0] => "url1"
            [1] => Array 
                    (
                        [url2] => Array 
                                   ( 
                                      [0] => "suburl1" 
                                   )
                    )
        )
    [page2] => Array
        (
            [0] => "url3"
            [1] => Array 
                    (
                        [url4] => Array 
                            (
                                [0] => "suburl2"
                                [1] => "suburl3"
                            )
                    )
        )
                    
)

I've seen this question: how to merge multiple url/path into multidimensional array? But it doesn't work in my case where the URLs are not the same dimension and also when I have URL like page1 and not /page1 it breaks it and create a string key and also an array key with that URL:

$urls = [
'page1',
'page1/url1',
'page1/url2/suburl1',
'page2/url3',
'page2/url4/suburl2',
'page2/url4/suburl3'
];

$paths = [];
foreach ($urls as $url) {
    $path_parts = explode('/', $url);
    $path = [array_pop($path_parts)];
    foreach (array_reverse($path_parts) as $path_part) {
        $path = [$path_part => $path];
    }    
    $paths[] = $path;
}

$tree = call_user_func_array('array_merge_recursive', $paths);

print_r($tree);

(Demo: https://onlinephp.io/c/02a524)

You can see for example:

Array
(
    [0] => page1
    [page1] => Array
1
  • 1
    Please provide your code within the question as well, otherwise it can be deemed off topic (see the help center) Commented Jun 28, 2023 at 6:41

1 Answer 1

1

You could try with:

<?php

$urls = [
    'page1',
    'page1/url1',
    'page1/url2/suburl1',
    'page2/url3',
    'page2/url4/suburl2',
    'page2/url4/suburl3'
];

function insert(&$array, $keys) {
    $key = array_shift($keys);
    if(empty($keys)) {
        if(!isset($array[$key])) {
            $array[] = $key;
        }
    } else {
        if(!isset($array[$key]) || !is_array($array[$key])) {
            $array[$key] = [];
        }
        insert($array[$key], $keys);
    }
}

// Sort and filter the URLs
sort($urls);
$urls = array_filter($urls, function($url) {
    return substr_count($url, '/') > 0;
});

$result = [];
foreach($urls as $url) {
    $parts = explode('/', $url);
    insert($result, $parts);
}

print_r($result);

?>

Output:

Array
(
    [page1] => Array
        (
            [0] => url1
            [url2] => Array
                (
                    [0] => suburl1
                )

        )

    [page2] => Array
        (
            [0] => url3
            [url4] => Array
                (
                    [0] => suburl2
                    [1] => suburl3
                )

        )

)
Sign up to request clarification or add additional context in comments.

5 Comments

thanks! It does work, but, is there a way make the "base" url as a value inside the array if it exists? For example for page1, since the base exists, it would be inside the [page1] => '/', instead of twice both outside and as the array key?
Because right now it still does the double issue as in my example at the bottom of the post for the inner urls
Post desired output, now I'm following the current one.
If you are talking about "[0] => page1", check updated answer.
Thank you! There are a few issues with the updated code: It ignores URLs that have no sub-urls, and also, it still adds double values for the inner arrays. For example, it both adds [0] => 'url1' and also [url1] => array(..). Example: onlinephp.io/c/e9e43

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.