Forum Webscript.Ru

Программирование => PHP => Тема начата: AlieN от 23 Мая 2002, 15:22:58

Название: Категории -> Подкатегория -> и т.д.
Отправлено: AlieN от 23 Мая 2002, 15:22:58
Есть небольшой трабл:
надо сделать система категорий и подкатегорий и использованием базы.
Как я себе это вижу: у каждой категории есть два идентификатора: уникальный ID и идентификатор родительской категории PARENT_ID.Возможно  здесь я ошибся......

Естественно у категорий есть элементы.

Мне требо вывести список "корневых" категорий предварительно подсчитав кол-во элементов во всех вложенных категориях....

Скорее всего это итерация но как на деле это реализовать я не понимаю
Название: Категории -> Подкатегория -> и т.д.
Отправлено: ThE0ReTiC от 23 Мая 2002, 15:34:02
Ну в принципе можно рекурсивно выбрать из базы родителей одного за другим пока не доберешься до корневого элемента.
Или просто сохранять путь при переходе в подкатегорию и добавлять ее при выводе.
Название: Категории -> Подкатегория -> и т.д.
Отправлено: AlieN от 23 Мая 2002, 15:35:48
ThE0ReTiC
ээээээ
ты предлагаешь корневых родителей держать в отдельной базе?

В общем распиши по подробнее плиз
Название: Категории -> Подкатегория -> и т.д.
Отправлено: ThE0ReTiC от 23 Мая 2002, 15:46:45
AlieN
Я тебе предлагаю сделать рекурсивную выборку из базы.
Что-то типа этого:

$res = mysql_query("SELECT page_id,category FROM table WHERE parent_id=$id AND category=$cat");

while(mysql_num_rows($res) != 0)
{
$id = mysql_fetch_row($res,"page_id");
$cat = mysql_+fetch_row($res,"category");
$res = mysql_query("SELECT page_id,category FROM table WHERE parent_id=$id AND category=$cat");
}
?>


Это информация к размышлению.
Я этот код не тестил.
Времени нет совсем.
Название: ИМХО
Отправлено: AliMamed от 23 Мая 2002, 16:09:23
Цитировать
Мне требо вывести список "корневых" категорий предварительно подсчитав кол-во элементов во всех вложенных категориях....

правильно и ресурсоемко в родительской категории иметь поле с количеством дочек.
Название: Категории -> Подкатегория -> и т.д.
Отправлено: Макс от 23 Мая 2002, 18:01:50
А еще есть алгоритм Nested Sets =>
http://www.e-taller.net/dbtree/
там класс для хранения деревьев в MySQL
Название: Категории -> Подкатегория -> и т.д.
Отправлено: AlieN от 23 Мая 2002, 18:32:18
Макс
Ты ссылку проверял?
Название: Категории -> Подкатегория -> и т.д.
Отправлено: Макс от 23 Мая 2002, 19:58:16
Упс, странно, ссылку из класса вытащил.
Вот рабочая:
http://dev.e-taller.net/dbtree/
Название: Категории -> Подкатегория -> и т.д.
Отправлено: AlieN от 24 Мая 2002, 09:49:28
Цитировать
поле с количеством дочек

а смысл?
Название: Категории -> Подкатегория -> и т.д.
Отправлено: Metaller от 24 Мая 2002, 10:07:10
AlieN
Слухай, Юрасик, что ж ты никак не хочешь использовать мою идею с TopLevelParent??? Тогда эта твоя проблема решается тривиально!

В каждой записи кроме Parent\'a еще записывай ИД корневого элемента данной ветки.
Тогда кол-во элементов будет

SELECT COUNT(*) as count FROM hren WHERE toplevel=$id

где $id - идешник текущего корневого элемента.
Название: Категории -> Подкатегория -> и т.д.
Отправлено: AlieN от 24 Мая 2002, 11:14:06
Metaller
Блин уже решили что без натравливания функции саму на себя не получается :)
Название: Категории -> Подкатегория -> и т.д.
Отправлено: Metaller от 24 Мая 2002, 11:21:55
AlieN
Формулируй конкретнее задачу. Для твоего вопроса мой вариант вполне подходит :)
Название: Категории -> Подкатегория -> и т.д.
Отправлено: Макс от 24 Мая 2002, 14:14:00
AlieN
Ты http://dev.e-taller.net/dbtree/ смотрел?
Там путь строится за 2 select-а при чем для любого уровня вложенности:

/*
* Пример работы с деревьями по алгоритму Nested Sets
*/
// параметры БД
$dbhost="localhost";
$dbuser="root";
$dbpassword="";
$dbname="cwb";
$tabname="test_tree"; // таблица с деревом

include("dbtree.php");
include("database.php");

$db = new CDatabase($dbname, $dbhost, $dbuser, $dbpassword);
$tree = new CDBTree ($db, $tabname, \'id\');

// создаем таблицу категорий
$query="CREATE TABLE IF NOT EXISTS $tabname(
id int unsigned not null auto_increment primary key,
cat_left int unsigned not null,
cat_right int unsigned not null,
cat_level int unsigned not null,
title varchar(128) not null)";
$db->query($query);

/** заполняем таблицу */
// сначало записываем корневой элемент
$levels = array();
$levels[0][0]=$tree->clear(array(\'title\'=>\'Начало\'));
// теперь записываем основную часть дерева
// элементы первого уровня вложенности
$levels[1][0] = $tree->insert($levels[0][0], array(\'title\'=>\'Программирование\'));
$levels[1][1] = $tree->insert($levels[0][0], array(\'title\'=>\'Отдых\'));
$levels[1][2] = $tree->insert($levels[0][0], array(\'title\'=>\'Работа\'));
$levels[1][3] = $tree->insert($levels[0][0], array(\'title\'=>\'Новости\'));
$levels[1][4] = $tree->insert($levels[0][0], array(\'title\'=>\'Спорт\'));
$levels[1][5] = $tree->insert($levels[0][0], array(\'title\'=>\'Романтика\'));
$levels[1][6] = $tree->insert($levels[0][0], array(\'title\'=>\'Политика\'));
$levels[1][7] = $tree->insert($levels[0][0], array(\'title\'=>\'Электронная коммерция\'));
$levels[1][8] = $tree->insert($levels[0][0], array(\'title\'=>\'Разное\'));

// элементы второго уровня вложенности
$levels[2][0] = $tree->insert($levels[1][0], array(\'title\'=>\'Web-программирование\'));
$levels[2][1] = $tree->insert($levels[1][0], array(\'title\'=>\'Теория\'));
$levels[2][2] = $tree->insert($levels[1][0], array(\'title\'=>\'Прикладное программирование\'));
$levels[2][3] = $tree->insert($levels[1][0], array(\'title\'=>\'Системное программирование\'));
$levels[2][4] = $tree->insert($levels[1][1], array(\'title\'=>\'Бары и рестораны\'));
$levels[2][5] = $tree->insert($levels[1][1], array(\'title\'=>\'Курорты\'));
$levels[2][6] = $tree->insert($levels[1][1], array(\'title\'=>\'Охота\'));
$levels[2][7] = $tree->insert($levels[1][1], array(\'title\'=>\'Рыбалка\'));
$levels[2][8] = $tree->insert($levels[1][2], array(\'title\'=>\'Поиск работы\'));
$levels[2][9] = $tree->insert($levels[1][2], array(\'title\'=>\'Удаленная работа\'));
$levels[2][10] = $tree->insert($levels[1][2], array(\'title\'=>\'Резюме\'));
$levels[2][11] = $tree->insert($levels[1][3], array(\'title\'=>\'Спортивные новости\'));
$levels[2][12] = $tree->insert($levels[1][3], array(\'title\'=>\'Погода\'));
$levels[2][13] = $tree->insert($levels[1][3], array(\'title\'=>\'Политические новости\'));
$levels[2][14] = $tree->insert($levels[1][4], array(\'title\'=>\'Футбол\'));
$levels[2][15] = $tree->insert($levels[1][4], array(\'title\'=>\'Баскетбол\'));
$levels[2][16] = $tree->insert($levels[1][5], array(\'title\'=>\'XXX\'));
$levels[2][17] = $tree->insert($levels[1][5], array(\'title\'=>\'НЛП\'));
$levels[2][18] = $tree->insert($levels[1][6], array(\'title\'=>\'Жириновский\'));
$levels[2][19] = $tree->insert($levels[1][6], array(\'title\'=>\'Путин\'));
$levels[2][20] = $tree->insert($levels[1][6], array(\'title\'=>\'Мао Цзедун\'));
$levels[2][21] = $tree->insert($levels[1][7], array(\'title\'=>\'B2B\'));
$levels[2][22] = $tree->insert($levels[1][8], array(\'title\'=>\'Пиво\'));
$levels[2][23] = $tree->insert($levels[1][8], array(\'title\'=>\'Водка\'));
$levels[2][24] = $tree->insert($levels[1][8], array(\'title\'=>\'Кременчуг\'));
$levels[2][25] = $tree->insert($levels[1][8], array(\'title\'=>\'Динамо Киев\'));
$levels[2][26] = $tree->insert($levels[1][8], array(\'title\'=>\'Чемпиоанат мира по футболу\'));
$levels[2][27] = $tree->insert($levels[1][8], array(\'title\'=>\'WebScript.Ru\'));

// 3-ий уровень
$levels[3][0] = $tree->insert($levels[2][0], array(\'title\'=>\'PHP\'));
$levels[3][1] = $tree->insert($levels[2][0], array(\'title\'=>\'PERL\'));
$levels[3][2] = $tree->insert($levels[2][0], array(\'title\'=>\'Java\'));
$levels[3][3] = $tree->insert($levels[2][1], array(\'title\'=>\'Алгоритмы\'));
$levels[3][4] = $tree->insert($levels[2][1], array(\'title\'=>\'Искуственный интелект\'));
$levels[3][5] = $tree->insert($levels[2][2], array(\'title\'=>\'С++\'));
$levels[3][6] = $tree->insert($levels[2][2], array(\'title\'=>\'Delphi\'));
$levels[3][7] = $tree->insert($levels[2][5], array(\'title\'=>\'Гаваи\'));
$levels[3][8] = $tree->insert($levels[2][5], array(\'title\'=>\'Канары\'));
$levels[3][9] = $tree->insert($levels[2][5], array(\'title\'=>\'нары\'));
$levels[3][10] = $tree->insert($levels[2][8], array(\'title\'=>\'в России\'));
$levels[3][11] = $tree->insert($levels[2][8], array(\'title\'=>\'за рубежом\'));
$levels[3][12] = $tree->insert($levels[2][22], array(\'title\'=>\'Балтика\'));
$levels[3][13] = $tree->insert($levels[2][27], array(\'title\'=>\'Форум\'));
$levels[3][14] = $tree->insert($levels[2][27], array(\'title\'=>\'Скрипты\'));
$levels[3][15] = $tree->insert($levels[2][27], array(\'title\'=>\'Хостобзор\'));
$levels[3][16] = $tree->insert($levels[2][27], array(\'title\'=>\'Статьи\'));

//  4-ый уровень
$levels[4][0] = $tree->insert($levels[3][0], array(\'title\'=>\'PHP2\'));
$levels[4][1] = $tree->insert($levels[3][0], array(\'title\'=>\'PHP3\'));
$levels[4][2] = $tree->insert($levels[3][0], array(\'title\'=>\'PHP4\'));

// 5-ый уровень
$levels[5][0] = $tree->insert($levels[4][2], array(\'title\'=>\'Работа с MySQL\'));

/** Таблицу заполнили */
/** Выведем наше дерево */
$query="SELECT id, title, cat_level FROM $tabname ORDER BY cat_left ASC";
$result=$db->query($query);
echo "Дерево
";
while ($row=$db->fetch_row($result)){
echo str_repeat("   ", $row[2]).$row[1]." (".$row[0].")
";
}

/** Находим путь к категории "Работа с MySQL", ее ID хранится в $levels[5][0] */
$id=$levels[5][0];

// сначало получаем ее параметры (cat_left и cat_right);
$result = $db->query("SELECT cat_left, cat_right, title FROM $tabname WHERE id=$id");
$row = $db->fetch_row($result);
$left=$row[0];
$right=$row[1];
$title=$row[2];
// получаем путь к данной категории
$query="SELECT id, title FROM $tabname WHERE cat_left<$left AND cat_right>$right ORDER BY cat_level ASC";
$result = $db->query($query);
$str="";
while($row = $db->fetch_row($result)){
echo $str.$row[1]."(".$row[0].")";
$str=">>";
}
echo $str.$title."(".$id.")
";
?>
Название: Категории -> Подкатегория -> и т.д.
Отправлено: AlieN от 24 Мая 2002, 17:07:59
Макс
Всё таки охота написать и понять самому :)
Название: Категории -> Подкатегория -> и т.д.
Отправлено: Макс от 24 Мая 2002, 17:48:21
AlieN
Цитировать
написать

Использование чужих классов - это вполне нормально в программировании
Цитировать
понять самому

С алгоритмом разобрался (nested sets)? Там главное - понять, что такое left и right и по какому принципу они ставятся. А дальше уже из этих знаний можно найти путь к текущей категории, или все подкатегории для указанной категории (смотря что нужно)

С database.php думаю все понятно (просто класс для работы с mysql)
А dbtree.php - читай комментарии, что делает каждый метод (а как он реализован - это уже не важно)
В том примере, что я набросал, к твоей теме относится только последние 19 строк (нахождение родительских категорий), все остальное - это подготовка таблицы (загонка информации о категориях + визуальное построение дерева)

PS
Мой совет - разберись, потом легче будет с деревьями работать. Я пока этот класс не нашел - сильно с деревьями извращался.


PPS
2 All
Может статью написать по этому алгоритму и классу?
Название: Категории -> Подкатегория -> и т.д.
Отправлено: Dm от 25 Мая 2002, 01:55:12
Макс
Цитировать
Может статью написать по этому алгоритму и классу?

имхо, актуально

AlieN
времени меньше будет уходить на разработку, если использовать готовые решения. просто нужно привыкнуть.
максимум - понять для себя алгоритм + проанализировать в работе.
Название: Категории -> Подкатегория -> и т.д.
Отправлено: KBA-KBA от 27 Мая 2002, 03:13:54
Да статью, это было бы хорошо... Тк подобные вещи очень нужны...