Недавно на работе мне была поставлена задача создать меню, древовидного типа , с сохранением уровней вложенности. Конечно можно было бы просто вывести все меню в раскрытом виде, с помощью рекурсии. Затем написать JavaScript код который бы собирал его и открывал по нажатию. Но мне этот вариант почему то не понравился. Пришлось писать. Сначало ломал голову как дать знать скрипту что он находится в определенном разделе и что раздел тоже вложенный и у него есть родительский пункт. Решение было как всегда простым.
Принцип таков:
Запускаем рекурсивную функцию которая проверяет в каком пункте меню находится пользователь . Она возвратит номера всех вхождений меню (всех родительских меню). А далее путем другой рекурсивной функции выводим все эти меню.
function IsMyParent($id)// возвращает айдишки всех пунктов меню в которые входит пункт меню выбранный пользователем { $sql = "SELECT pid FROM menu WHERE `id`='".(int)$id."' LIMIT 1"; $query = mysql_query($sql); $ids = array(); $ids[]=$id; while ($result=mysql_fetch_object($query)) { if ($result->pid>0){ $ids[] = $result->pid; } if ($result->pid>0){ $sql = "SELECT * FROM menu WHERE `id`='".$result->pid."' LIMIT 1"; $query = mysql_query($sql); if (mysql_num_rows($query)>0) { IsMyParent($result->pid); } } } asort($ids); return $ids; } function tree_show ($sub=0,$level,$menu_id,$ids=array()) { $sql = "SELECT * FROM menu WHERE pid='".(int)$sub."' "; $query = mysql_query($sql); if($level==0){echo '<ul id="nav">';} IsMyParent($menu_id); while ($row = mysql_fetch_array($query)) { echo '<li>'; echo '<a href='; echo "/index.php?menu=".$row[id]; echo ' >'; echo $row['menu_name']; echo '</a>'; foreach ($ids as $key=>$val) { if ($row['id']==$val){ $sql2 = "SELECT * FROM menu WHERE pid=".$row['id']; $query2 = mysql_query($sql2); $row2 = mysql_num_rows($query2); if ($row2!==0){ ++$level; echo '<ul>'; tree_show($row['id'],$level,$menu_id);--$level; echo '</ul>'; } } } echo '</li>'; } if($level==0){echo '</ul>';} }
Сразу хотел бы дать и таблицу для этого меню
CREATE TABLE `menu` ( `id` int(11) unsigned NOT NULL auto_increment, `menu_name` tinytext NOT NULL, `title` text NOT NULL, `content` text, `pid` int(11) default '0', `hide` int(11) NOT NULL, `active` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=98 DEFAULT CHARSET=utf8 AUTO_INCREMENT=98 ;
И на последок вызываем функцию:
tree_show(0,0,$_GET['menu']);
Мы получили полноценное древовидное меню на PHP.
Как заполнять таблицу БД? Какие данные заносить в pid, hide, active?
Алексанр, в pid — записывается значение родительского id.
hide и active — это вспомогательные элементы. Они служат для скрытия и соответственно отображения пункта меню. Для активации и деактивации. Они НЕ являются обязательными.
все можно в один запрос и короче. получить все, разбить на группы по pid и с помощью цыклов собрать, а сортировать средствами базы. иногда просто — это правильнее.