accessing array inside object inside array

  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

ok, is there any way i can get rid of the '$temp' variable in the following code?
im trying to create a new menuItem inside the array in the menuItem inside of $masterMenu[1]...
PHP Code: [ Select ]
$masterMenu[1] = new menuItem();
 
      $masterMenu[1]->setItem('<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>', array());
 
      $temp = $masterMenu[1]->getArray();
 
      $temp[0] = new menuItem();
  1. $masterMenu[1] = new menuItem();
  2.  
  3.       $masterMenu[1]->setItem('<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>', array());
  4.  
  5.       $temp = $masterMenu[1]->getArray();
  6.  
  7.       $temp[0] = new menuItem();

any ideas?
  • Anonymous
  • Bot
  • No Avatar
  • Posts: ?
  • Loc: Ozzuland
  • Status: Online

Post 3+ Months Ago

  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

sry for the double post... but ive been working on it, and i think ive made soem improvement but its still throwing an error at me...

Quote:
Parse error: parse error, unexpected T_OBJECT_OPERATOR in menus2.php on line 7


PHP Code: [ Select ]
<?php
 
   $masterMenu[0] = new menuItem();
 
      $masterMenu[0]->setItem('<a href = "/" class = "nav level1">Home</a>', array());
 
   $masterMenu[1] = new menuItem();
 
      $masterMenu[1]->setItem('<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>', array());
 
         $masterMenu[1]->createItem(0);
 
/*line 7*/  $masterMenu[1]->getMenu(0)->setItem('test1', array());
 
     
 
   class menuItem{         
 
      function setItem($alpha, $beta){
 
         $this->menuItem = $alpha;
 
         $this->subMenu = $beta;
 
      }
 
      function createItem($location){
 
         $this->subMenu[$location] = new menuItem();
 
      }
 
      function getEntry(){
 
         return $this->menuItem;
 
      }
 
      function getMenu($location){
 
         return $this->subMenu[$location];
 
      }
 
   }
 
?>
  1. <?php
  2.  
  3.    $masterMenu[0] = new menuItem();
  4.  
  5.       $masterMenu[0]->setItem('<a href = "/" class = "nav level1">Home</a>', array());
  6.  
  7.    $masterMenu[1] = new menuItem();
  8.  
  9.       $masterMenu[1]->setItem('<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>', array());
  10.  
  11.          $masterMenu[1]->createItem(0);
  12.  
  13. /*line 7*/  $masterMenu[1]->getMenu(0)->setItem('test1', array());
  14.  
  15.      
  16.  
  17.    class menuItem{         
  18.  
  19.       function setItem($alpha, $beta){
  20.  
  21.          $this->menuItem = $alpha;
  22.  
  23.          $this->subMenu = $beta;
  24.  
  25.       }
  26.  
  27.       function createItem($location){
  28.  
  29.          $this->subMenu[$location] = new menuItem();
  30.  
  31.       }
  32.  
  33.       function getEntry(){
  34.  
  35.          return $this->menuItem;
  36.  
  37.       }
  38.  
  39.       function getMenu($location){
  40.  
  41.          return $this->subMenu[$location];
  42.  
  43.       }
  44.  
  45.    }
  46.  
  47. ?>


what am i doing wrong?
  • this213
  • Guru
  • Guru
  • User avatar
  • Posts: 1260
  • Loc: ./

Post 3+ Months Ago

This is just a guess, so don't hang me if it's wrong, but:
PHP Code: [ Select ]
<?php
 
    $masterMenu[0] = new menuItem();
 
        $masterMenu[0]->setItem('<a href = "/" class = "nav level1">Home</a>', array());
 
    $masterMenu[1] = new menuItem();
 
        $masterMenu[1]->setItem('<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>', array());
 
            $masterMenu[1]->createItem(0);
 
      $masterMenu[1]->setItem('test1', array());
 
                $masterMenu[1]->getMenu(0);
 
 
 
    class menuItem{            
 
        function setItem($alpha, $beta){
 
            $this->menuItem = $alpha;
 
            $this->subMenu = $beta;
 
        }
 
        function createItem($location){
 
            $this->subMenu[$location] = new menuItem();
 
        }
 
        function getEntry(){
 
            return $this->menuItem;
 
        }
 
        function getMenu($location){
 
            return $this->subMenu[$location];
 
        }
 
    }
 
?>
  1. <?php
  2.  
  3.     $masterMenu[0] = new menuItem();
  4.  
  5.         $masterMenu[0]->setItem('<a href = "/" class = "nav level1">Home</a>', array());
  6.  
  7.     $masterMenu[1] = new menuItem();
  8.  
  9.         $masterMenu[1]->setItem('<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>', array());
  10.  
  11.             $masterMenu[1]->createItem(0);
  12.  
  13.       $masterMenu[1]->setItem('test1', array());
  14.  
  15.                 $masterMenu[1]->getMenu(0);
  16.  
  17.  
  18.  
  19.     class menuItem{            
  20.  
  21.         function setItem($alpha, $beta){
  22.  
  23.             $this->menuItem = $alpha;
  24.  
  25.             $this->subMenu = $beta;
  26.  
  27.         }
  28.  
  29.         function createItem($location){
  30.  
  31.             $this->subMenu[$location] = new menuItem();
  32.  
  33.         }
  34.  
  35.         function getEntry(){
  36.  
  37.             return $this->menuItem;
  38.  
  39.         }
  40.  
  41.         function getMenu($location){
  42.  
  43.             return $this->subMenu[$location];
  44.  
  45.         }
  46.  
  47.     }
  48.  
  49. ?>


At least - it doesn't throw out any errors
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

the reason its not throwing out errors is because you reset $masterMenu[1], its set on line 5, and the you set it again on line 7, you then called getMenu() and did nothing with it...

what i wouldnt give to be able to do this in Java right now... :P
  • this213
  • Guru
  • Guru
  • User avatar
  • Posts: 1260
  • Loc: ./

Post 3+ Months Ago

Don't know how I missed that one, I'll attribute it to my PHP newbie status.

Does this need to be object oriented? Forgive me if I'm wrong, but it just seems like you're trying to build something like this:
PHP Code: [ Select ]
<?php
 
   $masterMenu = array(
 
      '<a href = "/" class = "nav level1">Home</a>' => array('test1' => array()),
 
      '<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>' => array()
 
   );
 
?>
  1. <?php
  2.  
  3.    $masterMenu = array(
  4.  
  5.       '<a href = "/" class = "nav level1">Home</a>' => array('test1' => array()),
  6.  
  7.       '<a href = "/main.php?page=wow" class = "nav level1">World of Warcraft</a>' => array()
  8.  
  9.    );
  10.  
  11. ?>


or am I not reading it right?
  • rtm223
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 1855
  • Loc: Uk

Post 3+ Months Ago

Calendae, I have only just skimmed through this post, but are you trying to create a navigation with multiple levels? If you are, the words "binary tree" springs to mind.

If you are trying to do this and you don't know what a binary tree is then post back and I'll explain (I don't wanna explain the whole thing now in case I have the wrong end of the stick or if you already know about them!)
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

yes, it needs to be object oriented...
im not trying to use associated values...
the 'test1' was a string stored in an object i created, as was the array...
what i need to figure out how to do is how to access the functions of that object, which is inside an array, inside an object, which is inside '$masterMenu'...
no i have no idea what a binary tree is...
  • rtm223
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 1855
  • Loc: Uk

Post 3+ Months Ago

Ok, a word of warning: the binary tree method will be slightly harder to maintain, but will be a hell of a lot easier to code and probably easier to understand.

A Binary Tree is a list of items (in this case an array of objects) has two parts to it, information and pointers. For this we will use a single pointer, which will point to the <i>parent</i>. So you would define your navigational elements as having:

Id
ParentId
information - which is anything you might want.

In fact the Id could very well be the index of the object in the array.

So if we start off with the first level, which will all have the ParentId=-1, and then add levels as you go:

Code: [ Select ]
Array index | What is it | ParentId
-------------|--------------|-----------
0      | Node 1   |  -1
1      | Node 2   |  -1
2      | Node 3   |  -1
3      | Node 1.1  |   0
4      | Node 1.2  |   0
5      | Node 3.1  |   2  
6      | Node 1.2.1 |   4
  1. Array index | What is it | ParentId
  2. -------------|--------------|-----------
  3. 0      | Node 1   |  -1
  4. 1      | Node 2   |  -1
  5. 2      | Node 3   |  -1
  6. 3      | Node 1.1  |   0
  7. 4      | Node 1.2  |   0
  8. 5      | Node 3.1  |   2  
  9. 6      | Node 1.2.1 |   4


The example above will come out like:

Code: [ Select ]

Node 1
 Node 1.1
 Node 1.2
  Node 1.2.1
Node 2
Node 3
 Node 3.1
  1. Node 1
  2.  Node 1.1
  3.  Node 1.2
  4.   Node 1.2.1
  5. Node 2
  6. Node 3
  7.  Node 3.1


As you can see the method is handy because you only need the one array, it is a really easy structure to build and work with because you can just add new nodes onto the bottom, have as many elements as you like, and as many levels as you like.

You can also move a node (by changing it's parent) and all of it's descendents will move acordingly. Just like a normal directory tree.

Whats the problem? You have to use filtering (ie array_filter() ) , and recursion to build the navigational elements.

check out <a href="http://www.ozzu.com/programming-forum/asp-recursion-issue-t26453.html&highlight=asp+recursion" target="_blank">this thread</a> where Rabid Dog was doing the same thing with ASP and a database, instead of an array of objects. If you decide to go this way and need a hand, just ask :wink:
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

yes, this is exactly what im trying to do, and it does look a hell of a lot easier...

the end result i want is to be able to stick a menu colom in my content database, and heve the entry in it go something like '1.1.2.3' which would bring up this page: http://www.aysaedara.net/main.php?page= ... ace=undead
(not that i have the menus hard coded into the page right now...)

i would then have a routine that would go and make the menu based on that code...

i looked at the other topic, and well, im not really sure what is going on over there... :oops: so any help would be greatly appreciated...
  • rtm223
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 1855
  • Loc: Uk

Post 3+ Months Ago

Well this is perfect for a databases simply because it uses a simple list, obviously you can't nest stuff in a database well.

Well, after doing that with rabid dog, I built a shell of a php version, but it has never been tested and has none of the database code in it - I couldn't be bothered to build a database of pretend links lol.

Anyway, it's nearly half past midnight and I was planning on getting up early so I'll get back to you on this one tomorrow :wink:
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

mmmkay, sure, thanks alot :)
  • rtm223
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 1855
  • Loc: Uk

Post 3+ Months Ago

Well, so much for getting up early :roll:


Anyway I dug out my function, and now I remember it is a lot more complicated that what you need, it allows starting at any node and will allow you to specify maximum number of levels and stuff.


PHP Code: [ Select ]
 
function fullMenu(){
 
   return ("<ul id='fullmenu'>".menuCrawler(0)."</ul>");
 
}
 
function menuCrawler($parentId, $maxLevels){
 
   if(!isset($maxLevels)){$maxLevels=1000};                                //saves faffing later on in the recursion bit
 
   $sqlStr = "SELECT * FROM tblContents WHERE parent_Id='$parentId';";       
 
   $menuStr='';                                                      //initialise menuStr.  Local version.
 
   foreach(/*record returned*/){
 
         $menuStr+="<li>linky bit";                                     //start the list item
 
         if(/*has_children*/ && $maxLevels > 1){                              //if it has kiddies, go get them
 
            $menuStr+="<ul>".fullMenu(/*returned_Id*/,($maxLevels-1))."</ul>";      //recursive function call
 
         } 
 
         $menuStr+="</li>";                                             //end the list item.
 
      }
 
   }
 
   return $menuStr;
 
}
 
 
 
 
  1.  
  2. function fullMenu(){
  3.  
  4.    return ("<ul id='fullmenu'>".menuCrawler(0)."</ul>");
  5.  
  6. }
  7.  
  8. function menuCrawler($parentId, $maxLevels){
  9.  
  10.    if(!isset($maxLevels)){$maxLevels=1000};                                //saves faffing later on in the recursion bit
  11.  
  12.    $sqlStr = "SELECT * FROM tblContents WHERE parent_Id='$parentId';";       
  13.  
  14.    $menuStr='';                                                      //initialise menuStr.  Local version.
  15.  
  16.    foreach(/*record returned*/){
  17.  
  18.          $menuStr+="<li>linky bit";                                     //start the list item
  19.  
  20.          if(/*has_children*/ && $maxLevels > 1){                              //if it has kiddies, go get them
  21.  
  22.             $menuStr+="<ul>".fullMenu(/*returned_Id*/,($maxLevels-1))."</ul>";      //recursive function call
  23.  
  24.          } 
  25.  
  26.          $menuStr+="</li>";                                             //end the list item.
  27.  
  28.       }
  29.  
  30.    }
  31.  
  32.    return $menuStr;
  33.  
  34. }
  35.  
  36.  
  37.  
  38.  

As you can see it's just a mockup - half php and half pseudocode in notes - also bear in mind I've never done any php database work yet. It also includes support for a hasChildren field which will greatly reduce the number of queries.


from that other topic, this is the nested list we are going to be creating (lists are good for links - always put your links in lists!)
Code: [ Select ]
<ul>
  <li>Item Text here</li>
  <li>Parent Item Text here
    <ul>
      <li>Item Text here</li>
      <li>Item Text here</li>
      <li>Item Text here</li>
      <li>Item Text here</li>
    </ul>
  </li>
  <li>Item Text here</li>
  <li>Item Text here</li>
</ul>
  1. <ul>
  2.   <li>Item Text here</li>
  3.   <li>Parent Item Text here
  4.     <ul>
  5.       <li>Item Text here</li>
  6.       <li>Item Text here</li>
  7.       <li>Item Text here</li>
  8.       <li>Item Text here</li>
  9.     </ul>
  10.   </li>
  11.   <li>Item Text here</li>
  12.   <li>Item Text here</li>
  13. </ul>


I can't really think how to explain that function well. It uses recursion so that there can be any number of levels. Recursion is when a function calls itself. So, the function itself ONLY gets a single level, and then if any of the nodes has a child, it will call itself. When the second function call is completed the first then resumes from where it left off. So first function to be called is the last one to be completed.

I am struggling to explain this, it might be worth do a dry run (on paper) through this function with the eample I gave earlier. Bear in mind the version I showed you started with parent at -1, this requires the initial parent to be 0.
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

ok, this is what i have so far... and something is going terribly wrong...

PHP Code: [ Select ]
<?php
 
   include('sqlQuery.php');
 
   menuCrawler(2);
 
   
 
   function menuCrawler($parentID, $maxLevels = 15){
 
      $result = queryDB("SELECT ID, link FROM menus WHERE parentID = '" . $parentID. "'", true);
 
     
 
      $menuStr='';
 
      foreach($result as $node){
 
         $menuStr += "<li>" . $node[1];
 
         if(hasChildren($node[0]) && ($maxLevels > 1)){
 
            $menuStr += "<ul>" . menuCrawler($node[0] , ($maxLevels - 1)) . "</ul>";
 
         }    
 
         $menuStr += "</li>";
 
      }
 
      return $menuStr;
 
   }
 
   function hasChildren($nodeID){
 
      $result = queryDB("SELECT * FROM menus WHERE parentID = '" . $nodeID . "'", true);
 
      if(count($result) > 0){
 
         return true;
 
      }
 
      else{
 
         return false;
 
      }
 
   } 
 
?>
  1. <?php
  2.  
  3.    include('sqlQuery.php');
  4.  
  5.    menuCrawler(2);
  6.  
  7.    
  8.  
  9.    function menuCrawler($parentID, $maxLevels = 15){
  10.  
  11.       $result = queryDB("SELECT ID, link FROM menus WHERE parentID = '" . $parentID. "'", true);
  12.  
  13.      
  14.  
  15.       $menuStr='';
  16.  
  17.       foreach($result as $node){
  18.  
  19.          $menuStr += "<li>" . $node[1];
  20.  
  21.          if(hasChildren($node[0]) && ($maxLevels > 1)){
  22.  
  23.             $menuStr += "<ul>" . menuCrawler($node[0] , ($maxLevels - 1)) . "</ul>";
  24.  
  25.          }    
  26.  
  27.          $menuStr += "</li>";
  28.  
  29.       }
  30.  
  31.       return $menuStr;
  32.  
  33.    }
  34.  
  35.    function hasChildren($nodeID){
  36.  
  37.       $result = queryDB("SELECT * FROM menus WHERE parentID = '" . $nodeID . "'", true);
  38.  
  39.       if(count($result) > 0){
  40.  
  41.          return true;
  42.  
  43.       }
  44.  
  45.       else{
  46.  
  47.          return false;
  48.  
  49.       }
  50.  
  51.    } 
  52.  
  53. ?>


im getting an infinite error....
Quote:
Warning: Invalid argument supplied for foreach() in menus2.php on line 9
  • rtm223
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 1855
  • Loc: Uk

Post 3+ Months Ago

Well first off, why are you starting at 2?

Code: [ Select ]
menuCrawler(2);


I'm not sure why it is saying invalid argument? Can you use a foreach with a database (like I said, I've not got round to doing any database work yet). Alternatively you have started with parent ID = 2, and there may not be any nodes with parent ID=2. If it's returning no records it could be the foreach doesn't like that?

Any chance you can post the sample data you are working with?

Also bear in mind I never tested any of the code I posted, it was all theoretical.
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

ok, i wasnt thinking... my database starts with parentID 0... i wanted it to output this menu: http://www.aysaedara.net/main.php?page=wow i realize now that thats not how im susposed to do it, but i cant think of how to do it...
here is what is in the table 'menus' in my database...
Quote:
parentID - ID - link
0 - 0 - <a href = "/" class = "nav level1"...
0 - 1 - <a href ="/main.php?page=e2004" class ="nav level1...
0 - 2 - <a href ="/main.php?page=wow" class ="nav level1"...
0 - 3 - <a href ="/main.php?page=stargate" class ="nav lev...
2 - 0 - <a href =" /main.php?page=wow&sub=races" class =" ...
2 - 1 - <a href =" /main.php?page=wow&sub=classes" class ="...


and if i want to specify which menu i want wouldnt i have to specify something like '0.2.1.3' and then have it split it, and the determine the node by which level its at???

ie:
level0: node = 0
level1: node = 2 (for parentID = 0)
level2: node = 1 (for parentID = 2, super-parentID = 0)
level3: node = 3 (for parentID = 1, super-parentID = 2, super-super-parentID = 0)

or something along those lines??

and then i would have to revamp the database entries so that the parentIDs would read '0.2.1' and so forth...
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

well, assuming that what i said above is true... this is what i have so far...

PHP Code: [ Select ]
<?php
 
   include('sqlQuery.php');
 
   
 
   $level = '0';
 
   $menuStr = NULL;
 
   $nodes = NULL;
 
   $index = 0;
 
   
 
   $menu = generateMenu('0.2');
 
   echo($menu);
 
 
 
   function generateMenu($address){
 
      global $nodes;
 
      $nodes = explode('.', $address);
 
      $menu = menuCrawler();
 
      return $menu;
 
   }
 
   function menuCrawler(){
 
      global $level, $menuStr, $nodes, $index;
 
     
 
      $level += '.' . $nodes[$index];
 
      $result = queryDB("SELECT address FROM menus WHERE address = '" . $level . "'", true);
 
     
 
      for($i = 0; $i < count($result) - 1; $i++){
 
         $result = queryDB("SELECT ID, link FROM menus WHERE address = '" . $level . "'", true);
 
         foreach($result as $key => $item){
 
            $menuStr += "<li>" . $item[1];
 
            if($item[0] == $nodes[$index + 1]){
 
               $index += 1;
 
               $menuStr += "<ul>" . menuCrawler($level) . "</ul>";
 
            }
 
         }    
 
         $menuStr += "</li>";
 
      }
 
      return $menuStr;
 
   }
 
?>
  1. <?php
  2.  
  3.    include('sqlQuery.php');
  4.  
  5.    
  6.  
  7.    $level = '0';
  8.  
  9.    $menuStr = NULL;
  10.  
  11.    $nodes = NULL;
  12.  
  13.    $index = 0;
  14.  
  15.    
  16.  
  17.    $menu = generateMenu('0.2');
  18.  
  19.    echo($menu);
  20.  
  21.  
  22.  
  23.    function generateMenu($address){
  24.  
  25.       global $nodes;
  26.  
  27.       $nodes = explode('.', $address);
  28.  
  29.       $menu = menuCrawler();
  30.  
  31.       return $menu;
  32.  
  33.    }
  34.  
  35.    function menuCrawler(){
  36.  
  37.       global $level, $menuStr, $nodes, $index;
  38.  
  39.      
  40.  
  41.       $level += '.' . $nodes[$index];
  42.  
  43.       $result = queryDB("SELECT address FROM menus WHERE address = '" . $level . "'", true);
  44.  
  45.      
  46.  
  47.       for($i = 0; $i < count($result) - 1; $i++){
  48.  
  49.          $result = queryDB("SELECT ID, link FROM menus WHERE address = '" . $level . "'", true);
  50.  
  51.          foreach($result as $key => $item){
  52.  
  53.             $menuStr += "<li>" . $item[1];
  54.  
  55.             if($item[0] == $nodes[$index + 1]){
  56.  
  57.                $index += 1;
  58.  
  59.                $menuStr += "<ul>" . menuCrawler($level) . "</ul>";
  60.  
  61.             }
  62.  
  63.          }    
  64.  
  65.          $menuStr += "</li>";
  66.  
  67.       }
  68.  
  69.       return $menuStr;
  70.  
  71.    }
  72.  
  73. ?>


however, it is outputing a 0...
  • rtm223
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 1855
  • Loc: Uk

Post 3+ Months Ago

Calendae wrote:
Quote:
parentID - ID - link
0 - 0 - <a href = "/" class = "nav level1"...
0 - 1 - <a href ="/main.php?page=e2004" class ="nav level1...
0 - 2 - <a href ="/main.php?page=wow" class ="nav level1"...
0 - 3 - <a href ="/main.php?page=stargate" class ="nav lev...
2 - 0 - <a href =" /main.php?page=wow&sub=races" class =" ...
2 - 1 - <a href =" /main.php?page=wow&sub=classes" class ="...


Id=0 parentid=0. That will cause you problems, you will continually loop through that one node, placing it inside itself.

Quote:
and if i want to specify which menu i want wouldnt i have to specify something like '0.2.1.3' and then have it split it, and the determine the node by which level its at???

ie:
level0: node = 0
level1: node = 2 (for parentID = 0)
level2: node = 1 (for parentID = 2, super-parentID = 0)
level3: node = 3 (for parentID = 1, super-parentID = 2, super-super-parentID = 0)

I'm not entirely sure why you would need to know what level you are at at any one point? The idea of a tree i that you don't need the entire address. If you have the full address then you will start to get inconsistancies. #

Hang on I see what you have done, the Id's should be unique. For example
Quote:
parentID - ID - link
0 - 0 - <a href = "/" class = "nav level1"...
0 - 1 - <a href ="/main.php?page=e2004" class ="nav level1...
0 - 2 - <a href ="/main.php?page=wow" class ="nav level1"...
0 - 3 - <a href ="/main.php?page=stargate" class ="nav lev...
2 - 4 - <a href =" /main.php?page=wow&sub=races" class =" ...
2 - 5 - <a href =" /main.php?page=wow&sub=classes" class ="...

Because each node is an individual item. If you have lots of nodes with id=1, and a node with parentID=1, how can you know <B>which</B> node with ID 1 is the parent. If you have unique ID's you can get the full address by traversing the tree in to other way. Also check out the original example I showed you. The arrayindex is the same as the database ID. See how it is used in both cases.

having looked through your code and your menu, I can see a few other problems.

I now see that you need to know how many levels down you are to know which sections to have open. This makes things complicated but not as complicated as you have made them.

You are using both returns and global variables to build the $menuStr . Either method is viable, but you cannot use both at the same time. I chose the returns because it felt "neater" to me.

At the moment I think you are going to have to start with the node that you are at. Then work back up the tree to the very root node to get the address (as an array of Id's, call it $openId[] for eg). Then you modify the menu crawler to open the base menu, and any subsection node that is specified in the openId[] array.

I'll mock up an example, but I have no way of testing it because I am at work at the moment. Give me a bit and I'll edit it onto this post


PHP Code: [ Select ]
//Assume we know the current Node Id and it is held in the variable $thisPageId
 
 
 
$openId = array();
 
$openId[-1] = "";
 
 
 
 
 
getAddress($ThisPageId);
 
/*
 
This will giv us an array like:
 
-1 -> ""
 
2 -> ""
 
7 -> ""
 
 
 
which is the node Id=7 which has parentId=2, and 2 is a top level.
 
I've done it this way round, using keys instead of values so
 
that you can use isset().
 
*/
 
menu=makeMenu(-1);
 
 
 
function getAddress($currentNode){
 
    global $openId;
 
    $openId[$currentNode]="";    //Done this was so we can use isset later on
 
    //Get parent node for this node from the database
 
    if ($parentNode!=-1){
 
        getAddress($parentNode);
 
    }
 
}
 
 
 
 
 
function getMenu($parentId){
 
    //Get all nodes with parentId=$parentId
 
    global $openId;
 
    $menuStr='';
 
    foreach(/*results*/){
 
        $menuStr+="<li>"./*link from DB*/;
 
        if(isset($openId[/*currentIdfromDB*/])){
 
            $menuStr+="<ul>";
 
            $menuStr+=getMenu(/*currentIdfromDB*/);
 
            $menuStr+="</ul>";
 
        }
 
   menuStr+="</li>"
 
    }
 
}
  1. //Assume we know the current Node Id and it is held in the variable $thisPageId
  2.  
  3.  
  4.  
  5. $openId = array();
  6.  
  7. $openId[-1] = "";
  8.  
  9.  
  10.  
  11.  
  12.  
  13. getAddress($ThisPageId);
  14.  
  15. /*
  16.  
  17. This will giv us an array like:
  18.  
  19. -1 -> ""
  20.  
  21. 2 -> ""
  22.  
  23. 7 -> ""
  24.  
  25.  
  26.  
  27. which is the node Id=7 which has parentId=2, and 2 is a top level.
  28.  
  29. I've done it this way round, using keys instead of values so
  30.  
  31. that you can use isset().
  32.  
  33. */
  34.  
  35. menu=makeMenu(-1);
  36.  
  37.  
  38.  
  39. function getAddress($currentNode){
  40.  
  41.     global $openId;
  42.  
  43.     $openId[$currentNode]="";    //Done this was so we can use isset later on
  44.  
  45.     //Get parent node for this node from the database
  46.  
  47.     if ($parentNode!=-1){
  48.  
  49.         getAddress($parentNode);
  50.  
  51.     }
  52.  
  53. }
  54.  
  55.  
  56.  
  57.  
  58.  
  59. function getMenu($parentId){
  60.  
  61.     //Get all nodes with parentId=$parentId
  62.  
  63.     global $openId;
  64.  
  65.     $menuStr='';
  66.  
  67.     foreach(/*results*/){
  68.  
  69.         $menuStr+="<li>"./*link from DB*/;
  70.  
  71.         if(isset($openId[/*currentIdfromDB*/])){
  72.  
  73.             $menuStr+="<ul>";
  74.  
  75.             $menuStr+=getMenu(/*currentIdfromDB*/);
  76.  
  77.             $menuStr+="</ul>";
  78.  
  79.         }
  80.  
  81.    menuStr+="</li>"
  82.  
  83.     }
  84.  
  85. }


As you can see we create an array of the nodes we wish to open and then make the menu, opening nodes that are specified in the array.
This is not necessarilly accurate, I've just knocked it together again, and I have left all the database bits out. Note that any top-level node needs to have parentId = -1 for this to work. Then each node has a <b>completely unique</b> id, starting at 0.
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

ok, i think i see what youre getting at... but im thinking that that would be extreamly hard to maintain... is there any whay i could do it wiht the addresses i mentioned before?
  • rtm223
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 1855
  • Loc: Uk

Post 3+ Months Ago

not that hard to maintain. When you add a new page, you find the parent and you add the correct parent Id to it, which is basically how a normal filesystem works. Just think of the parents as directories.

Anyway the way your method falls down is if you want to alter your categorisation at a later date. think about moving a node in your system, you would have to manually edit the address of EVERY descendant node. My method, all of the descendants move automagically.

However, it is perfectly feasable to set up your method. First step would be to decide whether the string would be a global or a returned value. The best thing I can suggest is to do run through it manually, writing down exactly what is going on. Recursion can be a little bit difficult to understand, so it might be worth looking up some tutorials on it.
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

ok, i guess i didnt mean maintain... your way would be easier to maintain... but i think my way would be easier to use because you wouldnt have to remeber which ID goes with which menu... using my way, you just have to work your way down the chain... *shrug* that is what is easier to me anyway...

back to the code now... :P using returns would make everything easier... so thats what im going to do... however, it is saying that there is an 'Invalid Argument' in my foreach loop, and im not sure why...

PHP Code: [ Select ]
<?php
 
   include('sqlQuery.php');
 
   
 
   $nodes = NULL;
 
   $level = '';
 
   $index = NULL;
 
   
 
   $menu = generateMenu('0.3');
 
   echo($menu);
 
 
 
   function generateMenu($address){
 
      global $nodes;
 
      $nodes = explode('.', $address);
 
      $menu = menuCrawler();
 
      return $menu;
 
   }
 
   function menuCrawler(){
 
      global $level, $nodes, $index;
 
     
 
      $level += '.' . $nodes[$index];
 
     
 
      $current = $level;
 
     
 
      $result = queryDB("SELECT address FROM menus WHERE address = '" . $current . "'", true);
 
     
 
      for($i = 0; $i <= count($result) - 1; $i++){
 
         $result = queryDB("SELECT ID, link FROM menus WHERE address = '" . $current . "'", true);
 
         foreach($result as $key => $item){
 
            $menuStr += "<li>" . $item[1];
 
            if($item[0] == $nodes[$index + 1]){
 
               $index++;
 
               $menuStr += "<ul>" . menuCrawler($current) . "</ul>";
 
            }
 
         }    
 
         $menuStr += "</li>";
 
      }
 
      return $menuStr;
 
   }
 
?>
  1. <?php
  2.  
  3.    include('sqlQuery.php');
  4.  
  5.    
  6.  
  7.    $nodes = NULL;
  8.  
  9.    $level = '';
  10.  
  11.    $index = NULL;
  12.  
  13.    
  14.  
  15.    $menu = generateMenu('0.3');
  16.  
  17.    echo($menu);
  18.  
  19.  
  20.  
  21.    function generateMenu($address){
  22.  
  23.       global $nodes;
  24.  
  25.       $nodes = explode('.', $address);
  26.  
  27.       $menu = menuCrawler();
  28.  
  29.       return $menu;
  30.  
  31.    }
  32.  
  33.    function menuCrawler(){
  34.  
  35.       global $level, $nodes, $index;
  36.  
  37.      
  38.  
  39.       $level += '.' . $nodes[$index];
  40.  
  41.      
  42.  
  43.       $current = $level;
  44.  
  45.      
  46.  
  47.       $result = queryDB("SELECT address FROM menus WHERE address = '" . $current . "'", true);
  48.  
  49.      
  50.  
  51.       for($i = 0; $i <= count($result) - 1; $i++){
  52.  
  53.          $result = queryDB("SELECT ID, link FROM menus WHERE address = '" . $current . "'", true);
  54.  
  55.          foreach($result as $key => $item){
  56.  
  57.             $menuStr += "<li>" . $item[1];
  58.  
  59.             if($item[0] == $nodes[$index + 1]){
  60.  
  61.                $index++;
  62.  
  63.                $menuStr += "<ul>" . menuCrawler($current) . "</ul>";
  64.  
  65.             }
  66.  
  67.          }    
  68.  
  69.          $menuStr += "</li>";
  70.  
  71.       }
  72.  
  73.       return $menuStr;
  74.  
  75.    }
  76.  
  77. ?>
  • Cae
  • Expert
  • Expert
  • User avatar
  • Posts: 734

Post 3+ Months Ago

well, i did it, it works! w00t! :D

i just though id share the final scripts incase anyone wants to use it... subsequently, i realized after the fact, that i made this using strings, not integers, or doubles... :) so you dont have to have '00.03.00' menu codes and so forth... you can also use menu codes such as 'root.WoW.races' which is cool... :)

heres the final script:
PHP Code: [ Select ]
function generateMenu($address){
 
      global $nodes, $index, $level;
 
      $index = 0;
 
      $level = '';
 
      $nodes = explode('.', $address);
 
     
 
      $menu = menuCrawler();
 
      return $menu;
 
   }
 
   function menuCrawler(){
 
      global $level, $nodes, $index;
 
      $menuStr = '';
 
     
 
      if($index == 0){
 
         $level = $nodes[0];
 
      }
 
      else{
 
         $level = $level . '.' . $nodes[$index];
 
      }
 
      $current = $level;
 
      $indent = $index;
 
     
 
      $result = queryDB("SELECT ID, link FROM menus WHERE address = '" . $current . "' ORDER BY ID", 'menu');
 
      for($i = 0; $i <= count($result) - 1; $i++){
 
         $menuStr = $menuStr . str_replace("%level%", ('level' . $indent), $result[$i][1]) . chr(13) . chr(10);
 
         if($result[$i][0] == $nodes[$index + 1]){
 
            $index++;
 
            $menuStr = $menuStr . menuCrawler($current);
 
         }
 
      };
 
      return $menuStr;
 
   }
  1. function generateMenu($address){
  2.  
  3.       global $nodes, $index, $level;
  4.  
  5.       $index = 0;
  6.  
  7.       $level = '';
  8.  
  9.       $nodes = explode('.', $address);
  10.  
  11.      
  12.  
  13.       $menu = menuCrawler();
  14.  
  15.       return $menu;
  16.  
  17.    }
  18.  
  19.    function menuCrawler(){
  20.  
  21.       global $level, $nodes, $index;
  22.  
  23.       $menuStr = '';
  24.  
  25.      
  26.  
  27.       if($index == 0){
  28.  
  29.          $level = $nodes[0];
  30.  
  31.       }
  32.  
  33.       else{
  34.  
  35.          $level = $level . '.' . $nodes[$index];
  36.  
  37.       }
  38.  
  39.       $current = $level;
  40.  
  41.       $indent = $index;
  42.  
  43.      
  44.  
  45.       $result = queryDB("SELECT ID, link FROM menus WHERE address = '" . $current . "' ORDER BY ID", 'menu');
  46.  
  47.       for($i = 0; $i <= count($result) - 1; $i++){
  48.  
  49.          $menuStr = $menuStr . str_replace("%level%", ('level' . $indent), $result[$i][1]) . chr(13) . chr(10);
  50.  
  51.          if($result[$i][0] == $nodes[$index + 1]){
  52.  
  53.             $index++;
  54.  
  55.             $menuStr = $menuStr . menuCrawler($current);
  56.  
  57.          }
  58.  
  59.       };
  60.  
  61.       return $menuStr;
  62.  
  63.    }


and heres an example of the database (dashes denote next colom):
Quote:
address - ID - link
00 - 03 - <a href ="/main.php?page=wow" class ="nav %level%"...
00.03 - 04 - <a href = "/main.php?page=wow&sub=basics" class = ...
00.03.00 - 00 - <a href = "/main.php?page=wow&sub=races&side=allia...
00.03.00 - 01 - <a href = "/main.php?page=wow&sub=races&side=horde...
00.03.00.00 - 00 - <a href = "main.php?page=wow&sub=races&side=allian...
00.03.00.00 - 01 - <a href = "main.php?page=wow&sub=races&side=allian...


enjoy!

//yay! and thanks rtm223 :)

Post Information

  • Total Posts in this topic: 21 posts
  • Users browsing this forum: No registered users and 123 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.