- How to create a nested menu from MySQL with PHP?
- 3 Answers 3
- Алгоритм работы состоит из следующего:
- Создаем соединение с базой данных
- Пишем функцию получения данных из таблицы Categories
- Получаем массив вот такого вида, где ключ массива это ID категории.
- Функция построения дерева из массива от Tommy Lacroix
- Получаем массив в виде дерева
- Скрипт целиком
- Результат работы
- Многоуровневое меню на PHP + MySQL для админки
- Create a dynamic menu in PHP
- Create a dynamic menu in PHP from your MySQL data
- Put all the PHP code into a single function
- A PHP function which is used to manipulate the query string
- Example PHP dynamic menu usage
- Related Posts
- 2 Comments
How to create a nested menu from MySQL with PHP?
I need to create a menu with PHP from a MySQL database. Table called categories has id, name, parent_id, shortdesc, etc. The output need to have parent list and children list under the partent list as follows. If you can show me codes or website, I will appreciate it.
3 Answers 3
This is specifically for two levels deep. Recommended approach should it be more is to use an optimized table structure for traversal, like http://articles.sitepoint.com/article/hierarchical-data-database/2 (pointed out elsewhere) or to pull the data you need and push it into a dictionary (associative array) and query it that way.
If you have only two levels then, you could just display them :
If you have an undefined number of submenus however you should use a Recursive Function.
So every of your subcategories, whatever their number is will be displayed.
You make database like this.
ID NAME PARENT 0 Cars -1 1 Foods -1 2 Ford 0 3 Honda 0 4 Toyota 0 5 Pasta 1 6 Pizza 1 .
You query them all up and put it in an array.
$Menus = array(); // In a read MySQL loop $Menus[$i]['ID'] $Menus[$i]['NAME'] $Menus[$i]['PARENT'] // Sorry, lazy to write. I think you know what I mean.
Then you loop all menu looking for PARENT == -1. Generate all UL and IL then sub it with another nested menu. You can simply create a function like this.
var $MenuLevelClass = array("menulist"); function CreateMenu($Menus, $Tab = 0, $Parent = -1, $Level = 0) { global $MenuLevelClass; $CatClass = ($Level != 0) ? '' : ' '; $MenuClass = $MenuLevelClass[$Level]; if ($MenuClass != '') $MenuClass = ' '; $TabCount = $Level + $Tab; $TabUL = ""; for ($t = 0; $t < $TabCount; $t++) $TabUL = $TabUL."\t"; $TabLI = $TabUL."\t"; ?>> >
And to use it just run ' CreateMenu($Menus); ' or ' CreateMenu($Menus, $PrefixTabCount); '. CreateMenu will recursively create the nested menu for you.
I have not test it so you may have to adjust it.
Многоуровневое меню на PHP + MySQL
Ни один сайт не обходится без навигации или как еще называют "меню сайта". Так вот меню сайта бывает одноуровневым и многоуровневым в виде дерева. Если с одноуровневым меню особых сложностей в плане реализации не возникает, то при создании многоуровневого меню нужно хорошо подумать.
Самое главное в этой задаче это спроектировать базу данных для нашего многоуровневого меню. Создадим таблицу Categories с тремя полями id , title , parent где:
- ID – идентификатор
- Title – Название меню
- Parent – Родитель категории по умолчанию 0
За ветвление меню отвечает поле Parent если Parent = 0 , то эта категория является родительской. Для того чтобы добавить потомков к родительской категории нужно в поле parent указать ID нужного родителя. Например:
ID | TITLE | PARENT |
---|---|---|
1 | Автомобили | 0 |
2 | Мотоциклы | 0 |
3 | Мазда | 1 |
4 | Хонда | 1 |
5 | Кавасаки | 2 |
6 | Харлей | 2 |
7 | Лодки | 0 |
Как видно из таблицы, у родительской категории Автомобили есть два потомка – это Мазда и Хонда связанных по полю Parent . А у категории Мотоциклы два потомка – это Кавасаки и Харлей . При этом у категории Лодки нет потомков. Надеюсь, что Вы поняли,как связать категории.
Далее переходим от слов к практике. Создадим таблицу Categories.
CREATE TABLE IF NOT EXISTS `categories` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `parent` int(10) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=20 ; -- -- Дамп данных таблицы `categories` -- INSERT INTO `categories` (`id`, `title`, `parent`) VALUES (1, 'Автомобили', 0), (2, 'Мотоциклы', 0), (3, 'Мазда', 1), (4, 'Хонда', 1), (5, 'Кавасаки', 2), (6, 'Харлей', 2), (7, 'Мазда 3', 3), (8, 'Мазда 6', 3), (9, 'Седан', 7), (10, 'Хечбэк', 7), (11, 'Лодки', 0), (12, 'Лифтбэк', 8), (13, 'Кроссовер', 8), (14, 'Белый', 13), (15, 'Красный', 13), (16, 'Черный', 13), (17, 'Зеленый', 13), (18, 'Мазда CX', 3), (19, 'Мазда MX', 3);
Алгоритм работы состоит из следующего:
- Создаем соединение с базой данных
- Получаем все данные из таблицы Categories
- Обрабатываем полученные данные изменив ключ массива на номер ID
- Из обработанного массива строим дерево зависимостей неограниченной вложенности используя метод рекурсии для построения
- Выводим наше многоуровневое меню на экран
Создаем соединение с базой данных
query("SET NAMES 'utf8'"); /* * Это "официальный" объектно-ориентированный способ сделать это * однако $connect_error не работал вплоть до версий PHP 5.2.9 и 5.3.0. */ if ($mysqli->connect_error) < die('Ошибка подключения (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error); > /* * Если нужно быть уверенным в совместимости с версиями до 5.2.9, * лучше использовать такой код */ if (mysqli_connect_error())
Пишем функцию получения данных из таблицы Categories
//Получаем массив нашего меню из БД в виде массива function getCat($mysqli)< $sql = 'SELECT * FROM `categories`'; $res = $mysqli->query($sql); //Создаем масив где ключ массива является ID меню $cat = array(); while($row = $res->fetch_assoc()) < $cat[$row['id']] = $row; >return $cat; >
Получаем массив вот такого вида, где ключ массива это ID категории.
Далее нам нужно из этого массива построить дерево зависимости дочерних элементов от родительских проходя рекурсивно по всему массиву.
Функция построения дерева из массива от Tommy Lacroix
//Функция построения дерева из массива от Tommy Lacroix function getTree($dataset) < $tree = array(); foreach ($dataset as $id =>&$node) < //Если нет вложений if (!$node['parent'])< $tree[$id] = &$node; >else < //Если есть потомки то перебераем массив $dataset[$node['parent']]['childs'][$id] = &$node; >> return $tree; >
Получаем массив в виде дерева
Скрипт целиком
Результат работы
Многоуровневое меню на PHP + MySQL для админки
Если Вы хотите использовать данное меню в админке своего сайта, то нужно переписать пару функций tplMenu() , showCat() .
'.$category['title'].''; >else< $menu = ''; > if(isset($category['childs'])) < $i = 1; for($j = 0; $j < $i; $j++)< $str .= '→'; >$i++; $menu .= showCat($category['childs'], $str); > return $menu; > /** * Рекурсивно считываем наш шаблон **/ function showCat($data, $str) < $string = ''; $str = $str; foreach($data as $item)< $string .= tplMenu($item, $str); >return $string; > //Получаем HTML разметку $cat_menu = showCat($tree, ''); //Выводим на экран echo ''; ?>
Create a dynamic menu in PHP
The creation of a dynamic menu with a nested un-ordered list without using any JavaScript code is sometimes a problem because the script needs to “remember” the values, sub values and also the query string from previous clicked links. In this tutorial I will explain how to create a dynamic navigation menu using PHP and MySQ. While using standard HTML elements (un-ordered lists) it’s easy to add different CSS styles later. Follow this link for a demonstration example or download the PHP example files here.
First I need a database table holding the information for our navigation 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`) ) TYPE=MyISAM;
Create a dynamic menu in PHP from your MySQL data
Next I have to add some data for our PHP menu: menu items and sub-menu items.
Example: The menu item “Products” will have several sub-menu items and the record id is a “2”
All sub-menu items need the number “2” as value for the parent_id. The parent_id for each main menu item is a “0” (zero).
In the following code block I create a database result set and I add the value into a multi-dimensional arrays: $parent_menu and $sub_menu
The $parent_menu array is holding the label, the link (URL) and a count value that I need to decide if there is a sub-item or not. The $sub_menu array is holding the label and link values and the value of the parent_id.
I “loop” through the database result set to test each record’s parent_id is a zero (0) or not. If the value equal to “0” it’s a parent record and otherwise it becomes a sub-item record.
query("SELECT id, label, link_url, parent_id FROM dyn_menu ORDER BY parent_id, id ASC"); while ($obj = $items->fetch_object()) < 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; if (empty($parent_menu[$obj->parent_id]['count'])) < $parent_menu[$obj->parent_id]['count'] = 0; > $parent_menu[$obj->parent_id]['count']++; > > $items->close(); $db->close();
Put all the PHP code into a single function
For the creation of the whole navigation bar I a custom function, this way it’s more portable and I can access the code several times in different scripts without to write the code all over again.
The arguments of the function are both arrays, the name of the query string value that’s used to fold out the menu, the two ids used to identify the un-ordered lists with the CSS style and an extra name for some CSS pseudo class to give a main link element with sub-items a different look. A nested un-ordered list is a list with list items (“li” elements) and several other lists (“ul” elements). A main node can hold another lists or new “ul” elements.
To do this I start in my function with a “ul” element, to identify the element with CSS we add some id attribute here.
Inside the loop there is a test for the count value from parent items, if the count is not null the menu item query string value is added.
A PHP function which is used to manipulate the query string
The code block begins with a test for $_GET variable which is posted via the link from the parent menu item a new loop is opened to create a list with sub-items related to the parent item. Inside the statement the function rebuild_link() is called, a function which is used to manipulate the query string:
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; >>
The arguments for this function are the link from the array, the variable name and value from the parent menu item (to keep the list open). Inside the function the query string will be exploded and is getting rebuilt without becoming in trouble with existing parts or new variables. At the end, the function will return a modified link with all parts of the query string.
Example PHP dynamic menu usage
How to use this dynamic menu PHP function? It’s easy just echo the function name with all the function attributes:
echo dyn_menu($parent_menu, $sub_menu, 'menu', 'nav', 'subnav');
Don’t forget to try the PHP menu demo for a better understanding.
Related Posts
How-to create a PHP Password Generator Do you need a PHP password generator function for your user registration application or do…
Dynamic thumbnails from websites Since Alexa stopped offering their free thumbnail service last year a lot of thumbnail services…
How-to create a PHP Password Generator Do you need a PHP password generator function for your user registration application or do…
2 Comments
Good script. However, there seems to be an error on lines 4 and 5 : $db = new mysqli(‘localhost’, ‘db_user’, ‘db_password’, ‘db_name’)) <
$items = $db->(“SELECT id, label, link_url, parent_id FROM dyn_menu ORDER BY parent_id, id ASC”); Line 4 : Should remove the ending ) < and replace /close it with ;
Line 5 : Forgot to add the query method $items = $db->query(“SELECT id, label, link_url, parent_id FROM dyn_menu ORDER BY parent_id, id ASC”);