Forum Webscript.Ru
		Программирование => PHP => Тема начата: AlieN от 23 Мая 2002, 15:22:58
		
			
			- 
				Есть небольшой трабл:
надо сделать система категорий и подкатегорий и использованием базы.
Как я себе это вижу: у каждой категории есть два идентификатора: уникальный ID и идентификатор родительской категории PARENT_ID.Возможно  здесь я ошибся......
Естественно у категорий есть элементы.
Мне требо вывести список "корневых" категорий предварительно подсчитав кол-во элементов во всех вложенных категориях....
Скорее всего это итерация но как на деле это реализовать я не понимаю
			 
			
			- 
				Ну в принципе можно рекурсивно выбрать из базы родителей одного за другим пока не доберешься до корневого элемента.
Или просто сохранять путь при переходе в подкатегорию и добавлять ее при выводе.
			 
			
			- 
				ThE0ReTiC 
ээээээ
ты предлагаешь корневых родителей держать в отдельной базе?
В общем распиши по подробнее плиз
			 
			
			- 
				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");
}
?>
Это информация к размышлению.
Я этот код не тестил.
Времени нет совсем.
			 
			
			- 
				
Мне требо вывести список "корневых" категорий предварительно подсчитав кол-во элементов во всех вложенных категориях.... 
правильно и ресурсоемко в родительской категории иметь поле с количеством дочек.
			 
			
			- 
				А еще есть алгоритм Nested Sets =>
http://www.e-taller.net/dbtree/
там класс для хранения деревьев в MySQL
			 
			
			- 
				Макс 
Ты ссылку проверял?
			 
			
			- 
				Упс, странно, ссылку из класса вытащил.
Вот рабочая:
http://dev.e-taller.net/dbtree/
			 
			
			- 
				
поле с количеством дочек
а смысл?
			 
			
			- 
				AlieN
Слухай, Юрасик, что ж ты никак не хочешь использовать мою идею с TopLevelParent??? Тогда эта твоя проблема решается тривиально!
В каждой записи кроме Parent\'a еще записывай ИД корневого элемента данной ветки.
Тогда кол-во элементов будет 
SELECT COUNT(*) as count FROM hren WHERE toplevel=$id
где $id - идешник текущего корневого элемента.
			 
			
			- 
				Metaller 
Блин уже решили что без натравливания функции саму на себя не получается :)
			 
			
			- 
				AlieN 
Формулируй конкретнее задачу. Для твоего вопроса мой вариант вполне подходит :)
			 
			
			- 
				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 
написать
Использование чужих классов - это вполне нормально в программировании 
понять самому 
С алгоритмом разобрался (nested sets)? Там главное - понять, что такое left и right и по какому принципу они ставятся. А дальше уже из этих знаний можно найти путь к текущей категории, или все подкатегории для указанной категории (смотря что нужно)
С database.php думаю все понятно (просто класс для работы с mysql)
А dbtree.php - читай комментарии, что делает каждый метод (а как он реализован - это уже не важно)
В том примере, что я набросал, к твоей теме относится только последние 19 строк (нахождение родительских категорий), все остальное - это подготовка таблицы (загонка информации о категориях + визуальное построение дерева)
PS
Мой совет - разберись, потом легче будет с деревьями работать. Я пока этот класс не нашел - сильно с деревьями извращался.
PPS
2 All
Может статью написать по этому алгоритму и классу?
			 
			
			- 
				Макс 
Может статью написать по этому алгоритму и классу?
имхо, актуально
AlieN
времени меньше будет уходить на разработку, если использовать готовые решения. просто нужно привыкнуть.
максимум - понять для себя алгоритм + проанализировать в работе.
			 
			
			- 
				Да статью, это было бы хорошо... Тк подобные вещи очень нужны...