От автора: при создании сайтов практически всегда необходимо выводить меню, то есть определенный блок с навигацией либо по страницам, либо по категориям веб-приложения. И очень часто данное меню необходимо отобразить в виде многоуровневого дерева. И хорошо, если предусматривается только второй уровень вложенности. А если третий? Или, вообще, неограниченный уровень вложенности? Как быть в этом случае? Поэтому в данном уроке мы с Вами научимся выводить на экран многоуровневое меню с неограниченным уровнем вложенности.
1. Создание базы данных.
Первым делом, как всегда, необходимо определиться со структурой базы данных. Так как чтобы выводить меню, необходимо, где то хранить его данные. Итак, давайте создадим базу данных, с названием data_car. Мы с Вами будем выводить категории для автомобильного сайта, поэтому и имя базы данных я выбрал близкое к этой тематике.
Итак, вот такая структура таблицы (таблицу назовем categories) нам понадобится для вывода, и хранения данных многоуровневого меню:
Теперь описание полей таблицы:
id – идентификатор таблицы (как обычно идентификаторы AUTO_INCREMENT и PRIMARY KEY)
title – заголовок категорий
parent_id – идентификатор родительской категории. По умолчанию и если категория родительская, значит значение данного поля 0, для определенной записи. Если же категория дочерняя, то в данном поле указываем идентификатор категории родителя (то есть поля id).
Теперь давайте наполним базу данных контентом, вставим в таблицу несколько родительских, категорий и несколько уровней дочерних, думаю три-четыре уровня вложенности, будет вполне достаточно.
Теперь, когда база данных создана, начнем создавать скрипт.
2. Основные настройки и подключение к базу данных.
Итак, давайте определимся с файловой структурой будущего скрипта. В данном уроке мы с Вами только лишь выведем блок с многоуровневым меню, поэтому нам понадобится, вот такой набор файлов и папок:
functions
— functions.php
config.php
index.php
Смотрите папка functions, содержит в себе один файл – functions.php, в котором будут описаны все функции необходимые для нормальной работы скрипта. Далее в файле config.php мы опишем все основные настройки и конечно index.php – основная точка входа.
Хочу сразу сказать, что все файлы, которые мы будем создавать, необходимо сохранять в кодировке UTF-8.
Итак, давайте посмотрим, какие основные настройки нам потребуются, вот код файла config.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php /** * Основные настройки * подключения к базе данных */ //Хост define("HOST","localhost"); //Имя пользователя define("USER","Viktor"); //Пароль define("PASS","1234"); //имя базы данных define("DB","data_car"); ?> |
Как Вы видите, нам потребуются только лишь настройки для подключения к базе данных. Вы, конечно же, можете добавить в данный файл, дополнительные данные, которые необходимы для работы Вашего веб-приложения.
Далее давайте создадим новый файл functions.php (сохраним его в папку functions) и создадим в нем первую функцию, которая будет выполнять подключение к базе данных:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php /** * Основные функции */ //соединени с базой данных function db($host,$user,$pass,$database) { $db = mysql_connect($host,$user,$pass); if (!$db) { exit('Ошибка при подключении к базе данных'); } if(!mysql_select_db($database,$db)) { exit('База данных не существует'); } mysql_query('SET NAMES utf8'); } ?> |
Как Вы видите, очень простая функция, которая принимает четыре параметра: адрес сервера, базы данных, имя пользователя, пароль и название базы данных. Вначале выполняем соединение с сервером базы данных, используя функцию mysql_connect($host,$user,$pass), затем выбираем базу данных для работы — mysql_select_db($database,$db) и в конце определяем кодировку для работы с базой данных.
Теперь давайте создадим файл index.php и добавим в него первые строки кода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php /** * Основная точка входа */ //Отправляем заголовок с кодировкой header("Content-Type:text/html;charset=utf8"); //Подключаем файл с функциями и файл конфигурации include 'functions/functions.php'; include 'config.php'; //соединение с базой данных db(HOST,USER,PASS,DB); ?> |
Итак, первым делом, отправляем заголовок с кодировкой – функция header(«Content-Type:text/html;charset=utf8»). Затем подключаем два ранее созданных файла: файл конфигураций config.php и файл functions.php. И наконец, вызываем функцию db(), для подключения к серверу базы данных. Теперь давайте проверим в браузере, что у нас получилось. Если на экране, на данном этапе ничего не вывелось, то есть, нет сообщений об ошибках, значит мы на верном пути.
3. Получение массива категорий.
Для того чтобы вывести многоуровневое меню, без ограничения по уровню вложенности необходимо использовать рекурсию.
Рекурсия — это обращение функции к самой себе, другими словами вызов функции внутри кода функции самой себя.
Теперь поговорим о том, по какому принципу мы будем выводить многоуровневое меню. Данная задача (как и любая в программировании) имеет несколько решений. К примеру, одно из таких решений состоит в том, чтобы создать функцию (принимающая параметром идентификатор родительской категории), которая в своем коде формировала SQL запрос по выборке данных меню, по полю parent_id. То есть, при первом вызове функции, выбираются все записи, у которых поле parent_id = 0, затем parent_id = 1, далее parent_id = 2 и т.д. Далее в цикле вытягиваем данные из результата отработки SQL запроса и в этом же цикле вызываем данную функцию (рекурсивно саму на себя) и передаем ей идентификатор родительской категории, полученный у записи, вытащенной на данной итерации цикла. То есть на первой итерации мы с Вами вытаскиваем в переменную ассоциативный массив, в этом массиве есть ячейка с ключом parent_id, вот ее значение и передаем при вызове функции.
Данный метод, казалось бы, очень неплохой, во-первых, он отлично работает, а во-вторых, имеет очень красивую и краткую реализацию. Но есть существенный недостаток – происходит многократное обращение к базе данных и выполнение запросов по выборке данных. А это не очень хорошо.
Поэтому, мы пойдем по другому пути и решим поставленную задачу иначе. Итак, первым делом мы обратимся к базе данных и вытащим все категории, которые в ней содержатся. Далее из этих категорий сформируем массив, определенного вида. И только потом создадим функцию, которая будет обрабатывать данный массив и выводить категории на экран.
Итак, давайте в файле functions.php создадим функцию get_cat():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?php //Функция получения массива каталога function get_cat() { //запрос к базе данных $sql = "SELECT * FROM categories"; $result = mysql_query($sql); if(!$result) { return NULL; } $arr_cat = array(); if(mysql_num_rows($result) != 0) { //В цикле формируем массив for($i = 0; $i < mysql_num_rows($result);$i++) { $row = mysql_fetch_array($result,MYSQL_ASSOC); //Формируем массив, где ключами являются адишники на родительские категории if(empty($arr_cat[$row['parent_id']])) { $arr_cat[$row['parent_id']] = array(); } $arr_cat[$row['parent_id']][] = $row; } //возвращаем массив return $arr_cat; } } ?> |
Итак, смотрите, вначале формируем и выполняем SQL запрос по выборке всех данных из таблицы categories, далее проверяем, успешно ли выполнился запрос. Теперь конечно можно было бы просто при помощи цикла пройтись по результату, полученному из базы данных и создать ассоциативный массив данных по категориям. Но такой массив очень неудобно обрабатывать, поэтому его необходимо отсортировать в удобном порядке. Нужно сделать так, чтобы на выходе данной функции, получился массив ключами которого, были бы идентификаторы родительских категорий. И в каждой ячейке данного массива, содержался бы еще массив – всех категорий (дочерних), у которых идентификатор родительской категории равен ключу соответствующего массива. Другими словами отсортируем массив по дочерним категориям. Что мы с Вами и делаем. Описываем цикл for, в котором будем поочередно проходиться по каждой строке результирующей таблицы, полученной из базы данных. Затем в переменную $row, сохраняем массив данных – одной строки результирующей таблицы. А дальше формируем массив $arr_cat, у которого ключи соответствуют идентификаторам родительских категорий. И наконец, возвращаем массив $arr_cat, как результат работы функции в целом.
Теперь давайте в файле index.php вызовем данную функцию:
1 2 3 4 5 |
<?php //получаем массив каталога $result = get_cat(); print_r($result); ?> |
Вызываем функцию get_cat() и сразу же распечатаем полученный массив $result, чтобы убедиться, что все корректно работает:
Как Вы видите, функция действительно правильно работает и полученный массив категорий отсортирован в нужном порядке. Теперь, осталось создать функцию, которая и будет выводить данные категории в виде многоуровневого меню.
4. Вывод категорий в виде многоуровневого дерева.
Итак, давайте откроем файл functions.php и создадим функцию view_cat(), которая и будет выводить многоуровневое меню:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php //вывод каталога с помощью рекурсии function view_cat($arr,$parent_id = 0) { //Условия выхода из рекурсии if(empty($arr[$parent_id])) { return; } echo '<ul>'; //перебираем в цикле массив и выводим на экран for($i = 0; $i < count($arr[$parent_id]);$i++) { echo '<li><a href="?category_id='.$arr[$parent_id][$i]['id']. '&parent_id='.$parent_id.'">' .$arr[$parent_id][$i]['title'].'</a>'; //рекурсия - проверяем нет ли дочерних категорий view_cat($arr,$arr[$parent_id][$i]['id']); echo '</li>'; } echo '</ul>'; }?> |
Итак, данная функция принимает два параметра: первый – это собственно массив, который необходимо обработать, и второй идентификатор родительской категории, то есть той категории, данные которой, мы будем отображать. Замете, что если не передать второй параметр, то по умолчанию он равен нулю, то есть вначале отображаем родительскую категорию.
Так как данная функция будет рекурсивно вызываться, то первым делом необходимо описать условие выхода из рекурсии, что мы с Вами и делаем. А именно, проверяем, существует ли ячейка массива с ключом ($arr[$parent_id]) — идентификатором родительской категории – который передается параметром при вызове функции.
Далее выводим, открывающий тег ul — наше меню будем выводить в виде не нумерованного списка. И описываем цикл for, при помощи которого, будем проходить по элементам массива $arr. Затем между тегами li выводим ссылку на категорию.
Путь ссылки сформируем таким образом – при помощи GET параметров передадим две переменные: первая это идентификатор категории и вторая – идентификатор ее родительской категории. При этом, чтобы получить идентификатор категории — вначале обращаемся к ячейке массива $arr, по идентификатору родительской категории, который был передан как параметр к функции — $parent_id, затем – в этой ячейке у нас содержится так же массив, поэтому доступ к его ячейкам, получаем, используя счетчик цикла $i, и указываем непосредственно ключ, ассоциативного массива то есть [‘id’] – получаем идентификатор категории.
То есть, смотрите, когда мы будем вызывать данную функцию, конечно же, второй параметр ей передавать не будем, значит, по умолчанию он будет равен нулю, поэтому подразумевается что будем выводить только лишь родительские категории. Далее на первой итерации (шаге) цикла выводится первая ссылка на родительскую категорию, и затем рекурсивно вызываем опять же функцию view_cat(), передаем ей массив, который необходимо обработать и идентификатор данной категории (той которую мы только, что вывели на экран) — $arr[$parent_id][$i][‘id’], теперь он считается идентификатором родительской категории. Другими словами – проверяем, есть ли у данной категории – дочерние категории.
И наконец, после цикла выводим, закрывающий тег </ul>. На этом функция закончена. Теперь давайте перейдем в файл index.php и вызовем данную функцию:
1 2 3 4 5 6 |
<?php //Выводим каталог на экран с помощью рекурсивной функции echo '<div style="width:300px;float:left; padding:10px; border:1px solid #074776">'; view_cat($result); echo '</div>'; ?> |
Теперь давайте перейдем в браузер и посмотрим, что у нас получилось:
Как Вы видите, все отлично отработало, теперь можете поэкспериментировать, с категориями в базе данных и проверить, как выводятся категории четвертого-пятого уровня вложенности.
Надеюсь, данный урок будет Вам полезен. Удачного кодирования. И до новых встреч в следующих видео уроках.
Комментарии (30)