Home > Back-end >  Build URL path while recursively searching a hierarchical array for an id
Build URL path while recursively searching a hierarchical array for an id

Time:10-25

I have a multidimensional array and I want to build an url providing only the id of the children.

array (
  0 => 
  array (
    'id' => '1',
    'p_pag' => '0',
    'link' => 'Contact',
    'children' => 
    array (
      0 => 
      array (
        'id' => '2',
        'p_pag' => '1',
        'link' => 'Contact-County',
        'children' => 
        array (
          0 => 
          array (
            'id' => '3',
            'p_pag' => '2',
            'link' => 'Contact-Town-1',
            'children' => 
            array (
            ),
          ),
        ),
      ),
    ),
  ),
)

I expect a function where to specify the array above and the id as 3 in order to obtain an link like this /Contact/Contact-County/Contact-Town-1/

My attempt:

function getlink($array,$id)
{
    $link='';
    foreach($array as $aindex => $aval)
    {
        if($aval['id']==$id){$link.='/'.$aval['link'];}
        elseif($aval['children']){...}
    }
}

CodePudding user response:

You can use a recursive iterator. The iterator returns all elements of the array. You only have to filter out the elements that have the id you are looking for in the array. The solution assumes that this ID is unique and that an element 'link' exists in this subarray.

$iterator =  new \RecursiveIteratorIterator(
      new \RecursiveArrayIterator($arr),\RecursiveIteratorIterator::SELF_FIRST
);

foreach($iterator as $subarr){
  if(is_array($subarr) && array_key_exists('id',$subarr) && $subarr['id'] == $searchId){
    $link = $subarr['link']; 
    break;
  }
}

echo $link ? $link : 'not found';

Demo: https://3v4l.org/O0PAf

CodePudding user response:

Use a recursive approach where you traverse all children subarrays in search of the targeted id. When an id is found, start building the string as you return back up the branch until you hit the top level. When there are no parents to return to, the built string will be retirned from the function.

Code: (Demo)

function getLinkPathById(array $array, string $toId): ?string
{
    foreach ($array as $row) {
        if (
            $row['id'] === $toId
            || ($deeper = getLinkPathById($row['children'], $toId))
        ) {
            return '/' . $row['link'] . ($deeper ?? null);
        }
    }
    return null;
}

echo "1: " . getLinkPathById($array, 1) . PHP_EOL;
echo "2: " . getLinkPathById($array, 2) . PHP_EOL;
echo "3: " . getLinkPathById($array, 3) . PHP_EOL;
echo "4: " . getLinkPathById($array, 4);

Output from 4 different tests:

1: /Contact
2: /Contact/Contact-County
3: /Contact/Contact-County/Contact-Town-1
4: 
  • Related