PHP Forums Archive

Dynamic (2 level) navigation list - problem

Tags: php, dynamic, menu, arrays, navigation list, multilevel

jbn posted on 2009-01-11 15:40:25 #

Hello!

I can't get my menu to work
- Warning: Invalid argument supplied for foreach() in /home/adeniasys/domains/adeniasystems.se/public_html/test/mall/menutest.php on line 42

$parent_array data missing ?

$sql = "SELECT id, label, link_url, parent_id FROM dyn_menu ORDER BY parent_id, id ASC";
$items = mysql_query($sql);
while ($obj = mysql_fetch_object($items)) {
   if ($obj->parent_id == 0) {
       $parent_menu[$obj->id]['label'] = $obj->label;
       $parent_menu[$obj->id]['link'] = $obj->link_url;
   } else {
       $sub_menu[$obj->id]['parent'] = $obj->parent_id;
       $sub_menu[$obj->id]['label'] = $obj->label;
       $sub_menu[$obj->id]['link'] = $obj->link_url;
       $parent_menu[$obj->parent_id]['count']++;
   }
}
mysql_free_result($items);

function dyn_menu($parent_array, $sub_array, $qs_val = "menu", $main_id = "nav", $sub_id = "subnav", $extra_style = "foldout") {
   $menu = "<ul id=\"".$main_id."\">\n";
   foreach ($parent_array as $pkey => $pval) {
       if (!empty($pval['count'])) {
           $menu .= "  <li><a class=\"".$extra_style."\" rel="nofollow" href=\"".$pval['link']."?".$qs_val."=".$pkey."\">".$pval['label']."</a></li>\n";
       } else {
           $menu .= "  <li><a rel="nofollow" href=\"".$pval['link']."\">".$pval['label']."</a></li>\n";
       }
       if (!empty($_REQUEST[$qs_val])) {
           $menu .= "<ul id=\"".$sub_id."\">\n";
           foreach ($sub_array as $sval) {
               if ($pkey == $_REQUEST[$qs_val] && $pkey == $sval['parent']) {
                   $menu .= "<li><a rel="nofollow" href=\"".rebuild_link($sval['link'], $qs_val, $sval['parent'])."\">".$sval['label']."</a></li>\n";
               }
           }
           $menu .= "</ul>\n";
       }
   }
   $menu .= "</ul>\n";
   return $menu;
}

foreach ($parent_array as $pkey => $pval) {
   if (!empty($pval['count'])) {
       $menu .= "  <li><a class=\"".$extra_style."\" rel="nofollow" href=\"".$pval['link']."?".$qs_val."=".$pkey."\">".$pval['label']."</a></li>\n";
   } else {
       $menu .= "  <li><a rel="nofollow" href=\"".$pval['link']."\">".$pval['label']."</a></li>\n";
   }}

if (!empty($_REQUEST[$qs_val])) {
   $menu .= "<ul id=\"".$sub_id."\">\n";
   foreach ($sub_array as $sval) {
       if ($pkey == $_REQUEST[$qs_val] && $pkey == $sval['parent']) {
           $menu .= "<li><a rel="nofollow" href=\"".rebuild_link($sval['link'], $qs_val, $sval['parent'])."\">".$sval['label']."</a></li>\n";
       }
   }
   $menu .= "</ul>\n";
   }

function rebuild_link($link, $parent_var, $parent_val) {
   $link_parts = explode("?", $link);
   $base_var = "?".$parent_var."=".$parent_val;
   if (!empty($link_parts[1])) {
       $link_parts[1] = str_replace("&", "##", $link_parts[1]);
       $parts = explode("##", $link_parts[1]);
       $newParts = array();
       foreach ($parts as $val) {
           $val_parts = explode("=", $val);
           if ($val_parts[0] != $parent_var) {
               array_push($newParts, $val);
           }
       }
       if (count($newParts) != 0) {
           $qs = "&".implode("&", $newParts);
       }
       return $link_parts[0].$base_var.$qs;
   } else {
       return $link_parts[0].$base_var;
   }
} 

echo dyn_menu($parent_menu, $sub_menu, "menu", "nav", "subnav");

Can somone help ?

Comments / discussions

Olaf posted on 2009-01-11 15:42:57 #

add after this row

mysql_free_result($items);

the following code:

print_r($parent_menu);
print_r($sub_menu);

what do you get?

look if your data has the wrong structure (key) it will not work

jbn posted on 2009-01-11 18:38:18 #

Array ( [1] => Array ( [label] => Start [link] => # [count] => 2 ) [2] => Array ( [label] => Info [link] => # ) ) Array ( [3] => Array ( [parent] => 1 [label] => Test [link] => # ) [4] => Array ( [parent] => 1 [label] => Test2 [link] => # ) )
Warning: Invalid argument supplied for foreach() in /home/adeniasys/domains/adeniasystems.se/public_html/test/mall/menutest.php on line 44

Okey I´ll check structure key.=)

Olaf posted on 2009-01-11 18:41:01 #

looks like that the array $sub_menu is empty or does not exist...

jbn posted on 2009-01-11 18:44:24 #

I copied the sql question directly in to phpmyadmin and it doesnt work.

jbn posted on 2009-01-11 20:35:45 #

dyn_menu tabel

id label link_url parent_id
1 Start # 0
2 Info # 0
3 fef # 2
4 efe # 2

Olaf posted on 2009-01-11 20:57:38 #

that should work, export structure and data and post it here

jbn posted on 2009-01-11 21:17:59 #

-- phpMyAdmin SQL Dump
-- version 2.11.5
-- http://www.phpmyadmin.net
--
-- Värd: localhost
-- Skapad: 11 januari 2009 kl 22:08
-- Serverversion: 4.1.10
-- PHP-version: 5.2.5

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

--
-- Databas: adeniasys_tonys
--

-- --------------------------------------------------------

--
-- Struktur för tabell dyn_menu
--

CREATE TABLE dyn_menu (
id int(11) NOT NULL auto_increment,
label varchar(50) NOT NULL default '',
link_url varchar(100) NOT NULL default '#',
parent_id int(11) NOT NULL default '0',
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

--
-- Data i tabell dyn_menu
--

INSERT INTO dyn_menu VALUES(1, 'Start', '#', 0);
INSERT INTO dyn_menu VALUES(2, 'Info', '#', 0);
INSERT INTO dyn_menu VALUES(3, 'fef', '#', 2);
INSERT INTO dyn_menu VALUES(4, 'efe', '#', 2);

Olaf posted on 2009-01-11 21:20:58 #

and what do you get using this code?

$items = mysql_query($sql) or die(mysql_error());

jbn posted on 2009-01-11 21:28:27 #

nothing´- just the same as earlier

http://www.adeniasystems.se/test/home/index.php

jbn posted on 2009-01-11 22:06:02 #

Updated the code - error message gone but still no submenus..

function dyn_menu($parent_array, $sub_array, $qs_val = "menu", $main_id = "nav", $sub_id = "subnav", $extra_style = "foldout") {
  $menu = "<ul id=\"".$main_id."\">\n";
  foreach ($parent_array as $pkey => $pval) {
      if (!empty($pval['count'])) {
          $menu .= "  <li><a class=\"".$extra_style."\" rel="nofollow" href=\"".$pval['link']."?".$qs_val."=".$pkey."\">".$pval['label']."</a></li>\n";
      } else {
          $menu .= "  <li><a rel="nofollow" href=\"".$pval['link']."\">".$pval['label']."</a></li>\n";
      }
      if (!empty($_REQUEST[$qs_val])) {
          $menu .= "<ul id=\"".$sub_id."\">\n";
          foreach ($sub_array as $sval) {
              if ($pkey == $_REQUEST[$qs_val] && $pkey == $sval['parent']) {
                  $menu .= "<li><a rel="nofollow" href=\"".rebuild_link($sval['link'], $qs_val, $sval['parent'])."\">".$sval['label']."</a></li>\n";
              }
          }
          $menu .= "</ul>\n";
      }
  }
  $menu .= "</ul>\n";
  return $menu;
}

function rebuild_link($link, $parent_var, $parent_val) {
  $link_parts = explode("?", $link);
  $base_var = "?".$parent_var."=".$parent_val;
  if (!empty($link_parts[1])) {
      $link_parts[1] = str_replace("&amp;", "##", $link_parts[1]);
      $parts = explode("##", $link_parts[1]);
      $newParts = array();
      foreach ($parts as $val) {
          $val_parts = explode("=", $val);
          if ($val_parts[0] != $parent_var) {
              array_push($newParts, $val);
          }
      }
      if (count($newParts) != 0) {
          $qs = "&amp;".implode("&amp;", $newParts);
      }
      return $link_parts[0].$base_var.$qs;
  } else {
      return $link_parts[0].$base_var;
  }
}

// ----------

$sql = "SELECT id, label, link_url, parent_id FROM dyn_menu ORDER BY parent_id, id ASC";
$items = mysql_query($sql);
while ($obj = mysql_fetch_object($items)) {
  if ($obj->parent_id == 0) {
      $parent_menu[$obj->id]['label'] = $obj->label;
      $parent_menu[$obj->id]['link'] = $obj->link_url;
  } else {
      $sub_menu[$obj->id]['parent'] = $obj->parent_id;
      $sub_menu[$obj->id]['label'] = $obj->label;
      $sub_menu[$obj->id]['link'] = $obj->link_url;
      $parent_menu[$obj->parent_id]['count']++;
  }
}
mysql_free_result($items);

echo dyn_menu($parent_menu, $sub_menu, "menu", "nav", "subnav");

jbn posted on 2009-01-11 22:11:07 #

When I click on Info the URL changes to http://www.adeniasystems.se/test/home/index.php#?menu=2 but nothing more happens. When I change te URL to http://www.adeniasystems.se/test/home/index.php?menu=2

the submenu for info Opens! =)

Olaf posted on 2009-01-11 22:20:45 #

right it works fine, look this is not a valid URL:

http://www.adeniasystems.se/test/home/index.php#?menu=2

it's possible that some browser can't pass the quesystring

jbn posted on 2009-01-12 07:01:25 #

What if I want to open the whole menu and submenus directly, how can I do that ?

Olaf posted on 2009-01-12 09:00:06 #

look this tutorial is an example to show a "folded" navigation.

Expanding all items would be a different code example.

you can try to remove the test (IF clause) from this part:

foreach ($sub_array as $sval) {
              if ($pkey == $_REQUEST[$qs_val] && $pkey == $sval['parent']) {
                  $menu .= "<li><a href=\"".rebuild_link($sval['link'], $qs_val, $sval['parent'])."\">".$sval['label']."</a></li>\n";
              }
          }

jbn posted on 2009-01-12 09:28:57 #

Okey, That didn't work.

Olaf posted on 2009-01-12 15:47:54 #

you need to work on this function:

if you know a little php it should be possible to remove the code which is conditional:

function dyn_menu($parent_array, $sub_array, $qs_val = "menu", $main_id = "nav", $sub_id = "subnav", $extra_style = "foldout") {
  $menu = "<ul id=\"".$main_id."\">\n";
  foreach ($parent_array as $pkey => $pval) {
      if (!empty($pval['count'])) {
          $menu .= "  <li><a class=\"".$extra_style."\" href=\"".$pval['link']."?".$qs_val."=".$pkey."\">".$pval['label']."</a></li>\n";
      } else {
          $menu .= "  <li><a href=\"".$pval['link']."\">".$pval['label']."</a></li>\n";
      }
      if (!empty($_REQUEST[$qs_val])) {
          $menu .= "<ul id=\"".$sub_id."\">\n";
          foreach ($sub_array as $sval) {
              if ($pkey == $_REQUEST[$qs_val] && $pkey == $sval['parent']) {
                  $menu .= "<li><a href=\"".rebuild_link($sval['link'], $qs_val, $sval['parent'])."\">".$sval['label']."</a></li>\n";
              }
          }
          $menu .= "</ul>\n";
      }
  }
  $menu .= "</ul>\n";
  return $menu;
}

camdenite posted on 2009-07-16 12:28:12 #

Hi, What I think is wanted is that when you are on the parent page - or any of it's sub pages then all the sub pages of the parent need to be displayed. OOOH OK I might be able to work that out...

Probably not but I'll have a go...

bubamara posted on 2010-01-29 13:31:53 #

Hi, I need your help, I keep getting the following message:

Undefined index: count in C:\wamp\www\index.php on line 22

with this code:

$parent_menu[$obj->parent_id]['count']++;

my php version is: 5.3.0

thanks for any help!!!
student from Serbia

Olaf posted on 2010-01-29 13:45:20 #

It's just a warning, you will never get this warning on a production server.

you can add a "@" before the variable to hide the error

bubamara posted on 2010-01-29 15:40:42 #

just a warning, ok!!!! :)

But NOW I have a new problem, I only see first menu level, without submenu!

mysql example is:

id label link_id parent_id
1 home http... 0
2 contact ... 0
3 free ... 2

free inside contact, but my result is only HOME and CONTACT without FREE under contact!

PLEASE HELP!

Olaf posted on 2010-01-29 15:46:35 #

Maybe you're looking for a different result the menu works like this:
while clicking a parent item, the sub items should become visible. By default you see only the parent items

bubamara posted on 2010-01-29 22:25:16 #

Hi, I solved the problem! I'm not supposed to link parent menu, only submenu should have link! :)

Would you be able to help me writing php code that lists the whole / entirely menu with correct order (and the corresponding submenu)

something like:

ul
li (1 menu) li
li (2 menu)
ul
li (2.1 submenu) li
li (2.2 submenu) li
ul li //closed (2 menu)
li (3 menu)
li (4)
ul

your example is very good but I get only parts of the menu when I click on... only one submenu code at a time.

thanks to the previous engagement

student from Serbia

bubamara posted on 2010-01-29 22:32:49 #

FROM MYSQL BASE EXTRACT ALL MENU AND SUBMENU ITEMS ... EVERYTHING at the same time!!!
RESULT:

<div class="something-1">
<ul id="something-2">

<li><a rel="nofollow" href="#">1</a></li>
<li><a rel="nofollow" href="#">2</a>
<ul>
<li><a rel="nofollow" href="#">2.1</a></li>
<li><a rel="nofollow" href="#">2.2</a></li>
<li><a rel="nofollow" href="#">2.3</a></li>
</ul>
</li>
<li><a rel="nofollow" href="">3</a></li>
<li><a rel="nofollow" href="#">4</a>
<ul>
<li><a rel="nofollow" href="#">4.1</a></li>
<li><a rel="nofollow" href="#">4.2</a></li>
</ul>
</li>
</div>

jossiflautisto posted on 2010-02-02 10:51:46 #

Hi,

Thanks for this code.
I am trying to get it to work but I get an error on the line where the while loop starts.

The connection works.

I am also wondering where I should the codeblocks.
Should the while loop be in the head or in the body?

tons posted on 2010-12-30 00:05:23 #

Hi buddy Olaf!

First of all, CONGRATS FOR YOUR CODING!

Im trying to get the dynanic menu to work, but itsn't show "submenus", I just "copy and paste" exactly what you made, but doesn't work...

Any idea of the problem? any bug discovered?

Could you allow to download an working example, please? or send it to me, will be so appreciate it!

Thank you so much for your time!

Tons.

Olaf posted on 2010-12-31 16:12:41 #

Hello Tons,
Because you're not the first one who asked for the code, I used the tutorials code (again) to build a demo page. If you go back to the tutorial page, you will find a demo link. The demo has two versions which demonstrate how this dynamic list works. There is also a link to the database dump, which is used for this demo page.

I'm sure you will succeed if you follow the tutorial while using the example data.

You understand that I like to help, but I can't provide full working code, because you need some basic PHP skills which are not part of the tutorial. Think about the database connection, using phpmyadmin and several more...