PHP: Построение древовидных данных в PHP

Недавно, возникла потребность сделать древовидный, порядковый список категорий, в одном из проектов.

2 главных условий, которые преследовал: 1) в html должны наглядно показываться родительские элементы и их «дети»; 2) для всей операции 1 SQL запрос.

SQL-структура была такая:

+------------+--------------+------+-----+---------+----------------+
| FIELD          | Type             | NULL   | KEY | DEFAULT   | Extra 
+------------+--------------+------+-----+---------+----------------+
| categoryID | int(3)            | NO    | PRI   | NULL     | AUTO_INCREMENT  |
| parent       | int(3)            | NO    |        | 0          |                        |
| name        | varchar(255)   | NO    |        | NULL     |                        |
| slug          | varchar(255)   | NO    |        | NULL     |                        |
| pic           | varchar(255)   | YES   |        | NULL     |                        |
+------------+--------------+------+-----+---------+----------------+
5 rows IN SET (0.03 sec)

После запроса в БД массив получился такой.

Array
(
    [0] => Array
        (
            [categoryID] => 1
            [parent] => 0
            [name] => Фильмы
            [slug] => films
            [pic] => 
        )
 
    [1] => Array
        (
            [categoryID] => 2
            [parent] => 0
            [name] => Музыка
            [slug] => music
            [pic] => 
        )
[...]
)

Для удобной работы я сгруппировал массив по categoryID, заменив его ключи на этот идентификатор.

foreach ($data as $v)
$array[$v['categoryID']] = $v;

А вот и сама функция, которая пишет в глобальный массив $g_data результат своей рекурсивной работы.

function tree(&$data, $node_id, $lvl = 0)
{
   switch ($lvl)
   {
      // для каждой категории может быть действие (напр. присвоить id)
	case 0:
	$html = '<option style="font-weight:bolder;" disabled>- КОРЕНЬ -</strong>'."\n";
	break;
	default:
        // str_repeat делает отступ слева, в зависимости от уровня кат-ии. Это наглядно показывает юзеру родителя категории и его дочерний элемент. А если кат-я самая "верхняя", она выделяется стилем font-weight:bold
	$html = '<option '.($data[$node_id]['parent']==0?'style="font-weight:bold;':'').' value="'.$data[$node_id]['categoryID'].'">'.str_repeat('&nbsp;&nbsp;', $lvl) . $data[$node_id]['name'].'</option>'."\n";
    }
  $this->g_data['tree'] .= $html;
 
   // рекурсия
   foreach ($data as $row)
      if ($row['parent'] == $node_id)
         $this->tree($data, $row['categoryID'], $lvl + 1);
}

Остаётся только запустить процесс.

tree($array, 0);
  • Трэкбеки закрыты
  • Комментарии (2)
    • Илья
    • 10 января, 2010

    Уважаемый автор – не могли бы Вы пояснить некоторые моменты Вашего кода?



Введите код с картинки