|
|
|
| Есть таблица
CREATE TABLE rubrics(
id INT UNIQUE,
parent_id INT,
name VARCHAR
)
|
Задача:
Превратить, полученную одним запросом из базы данных таблицу, в иерархический массив.
Мне что-то в голову приходят только весьма ресурсоёмкие алгоритмы.
Есть соображения как оптимально построить такую функцию? | |
|
|
|
|
|
|
|
для: Eugene77
(01.07.2009 в 19:36)
| |
<?
$tree = array();
$list = array();
while($row = mysql_fetch_row($res))
{
$list[$row[0]] = array($row[1], $row[2]);
$tree[$row[1]][] = $row[0];
}
|
| |
|
|
|
|
|
|
|
для: Trianon
(01.07.2009 в 21:26)
| | Пока идеи не уловил.
Понял только, что зря я в структуре таблицы указал name.
Он там будет, конечно, и ещё некоторые поля будут,но они не связаны с иерархичностью. Поэтому, чтобы не путаться зря, давайте как будто структура таблицы вот такая:
CREATE TABLE rubrics(
id INT UNIQUE,
parent_id INT
)
|
| |
|
|
|
|
|
|
|
для: Eugene77
(02.07.2009 в 19:00)
| | давайте. | |
|
|
|
|
|
|
|
для: Trianon
(02.07.2009 в 19:15)
| | >давайте.
Спасибо, конечно, что вы разрешили, но посмотрите только что за ерунда у меня получается:
(вчера ночью, я что-то туда лишнее вписал. Вот что я имел в виду (ИСПРАВЛЕНО)):
<?php
class IE{
private $ie=array();
private $rubtic_names=array();
private $items=array(); // table of aticles with reference to rubrics
private function one_level_seach($root, $child, $key, &$brench){
If($root == $key){ // если такая ветка уже существует,просто добавим к ней нового потомка
// if(isset( $this -> $brench[$child])) { echo "secondary entry"; return true;}
$new = $brench + array($child => array());
return $new;
} // Если на этом уровне такой ветки нет, поищем на более "тонких" веточках
foreach($brench as $k =>$b) if($bb = $this -> one_level_seach($root, $child, $k, &$b)) break;
if(isset($bb)) if($bb) {
if(!is_array($bb)) return true; //незначительная ошибка. Ничего не делаем
unset($brench[$k]);
return $brench + array($k => $bb);
}
return false;
}
public function resorse2ie(&$resorse){
while ($l = mysql_fetch_assoc($resorse)) {
$this -> rubric_names[$l['id_rubric']] = array( // образуем массив имён рубрик
"name" => $l['name'],
"icon" => $l['icon'],
);
// Образуем иерархию рубрик
$child = (int)$l['id_rubric']; $parent = (int)$l['parent'];
if(isset( $this -> ie[$child])) { // найден корень у того, что было корнем
$this -> ie[$parent] = array($child => $this -> ie[$child]); // Присоединяем удлинённую ветку снова
unset($this -> ie[$child]); // Удаляем старую короткую ветку
continue;
}
// Рекурсивный обход всех веток в поисках этой рубрики
foreach($this -> ie as $k => $b) if($bb = $this -> one_level_seach($parent, $child, $k, &$b)) break;
if(isset($bb)) if($bb) {
if(!is_array($bb)) continue; //незначительная ошибка. Пропускаем запись (Повтор пары родитель-наследник)
$this -> ie[$k]=$bb;
unset($bb);
continue;
}
// если нигде нет, то создаём новый корень
$this -> ie[$parent] = array($child => array());
}
return ($this -> ie);
}
}
require_once("config.inc");
$q = "SELECT * FROM test.ie";
$r= mysql_query($q) or exit("<br> $q <br>".mysql_error());
$ie = NEW IE;
$tree = $ie -> resorse2ie(&$r);
print_r($tree);
?>
|
Как-то всё это очень уж бестолково выглядит!
Ну, а вообще-то - это мой первый класс в жизни.
Так что, пожалуйста, покритикуйте его.
И подскажите
1. как правильно оформлять такие классы?
2. Какой алгоритм может быть эффективнее?
3. Почему-то на вот эту строку:
<?
if(isset( $this -> $brench[$child]))
|
сыплются замечания. А как тогда определять, установлено ли значение переменной? Что-то никак не разберусь я с объектно ориентированным подходом : (
На всякий случай, если будет время протестировать, добавляю пример дампа таблицы:
--
-- Структура таблицы `ie`
--
CREATE TABLE IF NOT EXISTS `ie` (
`num` int(4) unsigned NOT NULL auto_increment,
`id_rubric` int(10) unsigned NOT NULL default '0',
`parent` int(10) unsigned NOT NULL default '0',
`name` varchar(40) NOT NULL,
`icon` varchar(40) NOT NULL,
PRIMARY KEY (`num`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COMMENT='Иерархия рубрик' AUTO_INCREMENT=6 ;
--
-- Дамп данных таблицы `ie`
--
INSERT INTO `ie` (`num`, `id_rubric`, `parent`, `name`, `icon`) VALUES
(1, 2, 1, 'первый корень', ''),
(2, 3, 1, 'второй корень', ''),
(3, 33, 3, 'первая ветка от 2 ветки', ''),
(4, 333, 33, 'первая ветка от 3 ветки', ''),
(5, 334, 33, 'вторая ветка от 3 ветки', '');
|
| |
|
|
|
|
|
|
|
для: Trianon
(02.07.2009 в 19:15)
| | Такой страшенный код получается потому что адрес ветки, который я передаю при вызове рекурсивной функции почему-то не позволяет мне модифицировать исходную ветку.
Те изменения, которые я делаю в рекурсивной функции,почему-то не передаются массиву из которого ссылка взята.
А может, я как всегда, что-то путаю.
А может, это такой прикол в ООП и надо делать как-то иначе.
В общем - запутался | |
|
|
|
|