0

I have a few categories in my database which I am retrieving using nested set model something like this(number in brackets represent depth):

New(1)
-General(2)
-Console(2)

Games(1)
-pc(2)
--emulator(3)
-ps3(2)

I then have a function to handle the multidimensional array and generate the navigation menu

--the model
this returns the following array from database

Array (
    [0] => Array ( [name] => News [depth] => 1 ) 
    [1] => Array ( [name] => General [depth] => 2 ) 
    [2] => Array ( [name] => Console [depth] => 2 ) 
    [4] => Array ( [name] => Games [depth] => 1 ) 
    [5] => Array ( [name] => PC [depth] => 2 ) 
    [6] => Array ( [name] => emulator [depth] => 3 ) 
    [8] => Array ( [name] => ps3 [depth] => 2 ) 
) 

--the controller

public function index()
{
$navTree = $this->getNavTree(); //gets array from model
$createNavTree = $this->_renderTree($navTree); //pass array to function
$this->load->view('testnavigation.php', $createNavTree);
}


function _renderTree($tree){    
    $current_depth = 0;
    $counter = 0;

    $result = '';

    foreach($tree as $node){
        $node_depth = $node['depth'];
        $node_name = $node['name'];
        $node_id = $node['categoryid'];

        if($node_depth == $current_depth){
            if($counter > 0) $result .= '</li>';            
        }
        elseif($node_depth > $current_depth){

            $result .= $counter == 0 ? '<ul id="nav">' : '<ul>';
            $current_depth = $current_depth + ($node_depth - $current_depth);
        }
        elseif($node_depth < $current_depth){
            $result .= str_repeat('</li></ul>',$current_depth - $node_depth).'</li>';
            $current_depth = $current_depth - ($current_depth - $node_depth);
        }
        $result .= '<li><a href="#">'.$node_name.'</a>';
        ++$counter;
    }
    $result .= str_repeat('</li></ul>',$node_depth).'</li>';
    $result .= '</ul>';     
    return $result;
}

--view

echo $createNavTree;

The list is created in the correct indented order, the issue I am having however is generating the links for each item for instance the link for emulator should be mysite.com/games/pc/emulator

How would I go about achieving this, any help be appreciated thanks?

ninjamaster
  • 83
  • 1
  • 6

1 Answers1

0

I would take the easy-route and build an array of cache-levels and previously-computed paths for each level. When the "base-level" of 1 is seen again, clear the cache so that you don't have any invalid entries:

This sample code should work with what you currently have (just place this code in above your current layout-rendering code and use $path as the URL):

function _renderTree($tree) {
    $depths = array();
    foreach ($tree as $node) {
        // build the current path
        $path = (($node['depth'] > 1) ? $depths[$node['depth'] - 1] : '') . $node['name'];

        // set the current path as the current depth's path (to be used for any deeper-nodes)
        $depths[$node['depth']] = $path . '/';

        ... layout rendering code ...
    }
}

What it does is, if the current path's depth is higher than 1 (which means that there is a parent depth), it will take the computed path for the parent (which should be full path for the parent, not just the parent's name), and then adds the current name to it - this will give you the full nested path. Then, it stores that generated path into the $depths array (indexed with the current depth) for any children to use.

In your sample, you specify you want the path for Emulator to be mysite.com/games/pc/emulator, emphasis on the lower-case and the domain name. Since we're using the $node['name'] in our path, you'll want to use strtolower():

$path = (($node['depth'] > 1) ? $depths[$node['depth'] - 1] : '') . strtolower($node['name']);

I would suggest adding the domain-name in the actual line for the <a></a> tags:

$result .= '<li><a href="http://mysite.com/' . $path . '">'.$node_name.'</a>';
newfurniturey
  • 37,556
  • 9
  • 94
  • 102