Jump to content
  • 0

Дерево


mario
 Share

Question

Добрый день. Сижу бьюсь над задачей создания сложного дерева...

Суть такова:

Имеется четыре таблицы:

type

id int;name varchar(255);

view

id int; type_id int; name varchar(255);

country

id int; name varchar(255);

city

id int; country_id int; name varchar(255);

Необходимо создать дерево которое выводит следующем образом:

Тип 1
Вид 1
Страна 1
город1
...
городN
Страна 2
город1
...
городN
...
Страна N
город1
...
городN
...
Вид N(далее понятно)
Тип 2
Вид 1
Страна 1
город1
...
городN
Страна 2
город1
...
городN
...
Страна N
город1
...
городN
...
Вид N(далее понятно)
...
Тип N

И что бы список стран и городов был одинаковым для всех видов и типов.

Вначале я, пошел по легкому пути, сделал вывод только Тип -> Вид, следующем образом

таблица catalog_tree

id;parent_id;name;

и следующий код:

function ShowTree ($parent_id) {
$sql = "SELECT `id`, `parent_id`, `name` FROM `catalog_tree` WHERE `parent_id` = $parent_id ORDER BY `id`";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
echo '<ul>';
while ($row = mysql_fetch_array($result)) {
echo '<li><a href="#id='.$row['id'].'">'.$row['name'].'</a></li>';
ShowTree ($row['id']);
}
echo '</ul>';
}
}

Выводит впринципе как надо, потом я начал думать а как же теперь прикрутить страны и города, к данному дереву.

Решил Создать те 4 таблицы, которые описал выше, и написать функции для того что бы вытягивалось в массив данные следующем образом:

функция Тип {выполняется мускуль запрос для таблицы Type; создается массив через функцию mysql_fetch_array;}

функция Вид {выполняется мускуль запрос для таблицы View; создается массив через функцию mysql_fetch_array;}

функция Страна {выполняется мускуль запрос для таблицы Country; создается массив через функцию mysql_fetch_array;}

функция Город {выполняется мускуль запрос для таблицы City; создается массив через функцию mysql_fetch_array;}

и создается функция Tree но вот с ней я уже оканчательно запутался... :)

Не как не соображу как передавать переменные type_id, country_id. Ведь переменные в функциях действуют только в функциях...

Выход для меня был использовать глобальные переменные (типа global $var;) для функции, но везде пишут что это нельзя использовать, и к тому же на хостинге отключены глобальные переменные register_globals off. Или я что то путаю (переменная global $var; не есть глобальная функция в суперглобальном массиве $GLOBALS)?

В наличии книга Разработка Web-приложений с помощью PHP и MySQL //авторы:Л.Веллинг и Л.Томсон и www.php.su, www.php.ru/manual/

Прошу помощи, тыкать носом, в какую сторону думать?... :)

Link to comment
Share on other sites

14 answers to this question

Recommended Posts

  • 0

а если создать многомерный массив? собственно и все, функция тип создает массив, потом к каждому типу добавляем вид как подмассив, а далее в каждый вид одн и тоже пихаем какой нить функцией, а потом весь массив через foreach выводим в отм виде который нравится)

Link to comment
Share on other sites

  • 0

Для меня сложность заключается в том, что надо страны и города использовать одни, т.е. из одной таблицы...

А так например мне понятно как построить дерево с вложенность 5,10, 20 и т.д... это для меня понятно, даже написанная функция описанная выше подходит для этого...

В голове крутился еще вариант, сделать две таблицы

type_view

id;parent_id;name;

country_city

id;parent_id;name;

И их осталось соединить, но тоже возникает вопрос, каким образом...:)

Кстати, для Тип-Вид вложенность не будет разростаться Ну к примеру Тип1 - Тип1.1 - Тип1.2 -Вид 1-Вид1.2... ну и тп... а будет только Тип 1 - Вид1...ВидN; Тип N - Вид1...ВидN;

А вот для Страна-Город, может разрастаться ну на реальном примере теперь Россия - Москва - Ю.окргу, С.округ,В.округ,З.округ.; Ну вот что то в этом плане...

а если создать многомерный массив? собственно и все, функция тип создает массив, потом к каждому типу добавляем вид как подмассив, а далее в каждый вид одн и тоже пихаем какой нить функцией, а потом весь массив через foreach выводим в отм виде который нравится)

а как потом формировать ссылку типа ?type=$id;view=$type_id;country=$cid;city=$country_id;

я сам алгоритм не могу продумать... :)

эмм... а может все реализовывать в одной функции

ну т.е. создаем функцию tree

в ней внутри уже выполнять запросы внутри while и цикл влаживать в цикл, ну если так делать, это за одно обращение к скрипту, будет делать немеренное количество запросов... :)

Edited by mario
Link to comment
Share on other sites

  • 0
а как потом формиро
вать ссылку типа ?type=$id;view=$type_id;country=$cid;city=$country_id;

так и выполнять, а при построении элементам с таким id применять clss="opened" ну так как то

Для меня сложность заключается в том, что надо страны и города использовать одни, т.е. из одной таблицы...

Это как раз самое легкое, создаем массив, и потом просто вставляем его везде так:

$array['type']['subtype']['cities']=$arr_with_inc;

Link to comment
Share on other sites

  • 0
вать ссылку типа ?type=$id;view=$type_id;country=$cid;city=$country_id;

так и выполнять, а при построении элементам с таким id применять clss="opened" ну так как то

не про что ты?

Это как раз самое легкое, создаем массив, и потом просто вставляем его везде так:

$array['type']['subtype']['cities']=$arr_with_inc;

а что же тогда самое сложно :)

Я не пойму как мне использовать переменные? между функциями. И если это в одной функции выполняется, то как быть с тем что будет выполняться фигова туча запросов к БД(или я не прав)?

Link to comment
Share on other sites

  • 0

возвращать каждой функцией массив. а потом один дугому присваивать...

вать ссылку типа ?type=$id;view=$type_id;country=$cid;city=$country_id;

так и выполнять, а при построении элементам с таким id применять clss="opened" ну так как то

как у тебя дерево строится? оно открывается/закрывается? каким обрзом? наверное меняется стиль(display;) вот и меняй присвоение класса)

Link to comment
Share on other sites

  • 0

я пока не ставил задачу на стилевое оформление

Вот у меня получилось построить то что я хочу.

таблицы geo_tree и catalog_tree, в первой хранятся страны и города, во второй типы и виды.

	function GeoTree ($country_id) {
$sql = "SELECT `id`, `country_id`, `name` FROM `geo_tree` WHERE `country_id` = $country_id ORDER BY `name`";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
echo '<ul>';
while ($row = mysql_fetch_array($result)) {
echo '<li><a href="#country='.$country_id.';city='.$row['id'].'">'.$row['name'].'</a></li>';
GeoTree ($row['id']);
}
echo '</ul>';
}
}

function CatalogTree ($parent_id) {
$sql = "SELECT `id`, `parent_id`, `name` FROM `catalog_tree` WHERE `parent_id` = $parent_id ORDER BY `id`";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
echo '<ul>';
while ($row = mysql_fetch_array($result)) {
echo '<li><a href="#id='.$row['id'].'">'.$row['name'].'</a></li>';
if ($row['id'] > 0) {
CatalogTree ($row['id']);
GeoTree (0);
}
}
echo '</ul>';
}
}

CatalogTree (0);

Но вот только не получается правильно оформить ссылки... точнее передачу параметров в ссылке...

Link to comment
Share on other sites

  • 0

	function CityGeoTree ($country_id) {
$sql = "SELECT `id`, `country_id`, `name` FROM `geo_tree` WHERE `country_id` = $country_id ORDER BY `name`";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
echo '<ul class="tree">';
while ($row = mysql_fetch_array($result)) {
echo '<li><a href="#city='.$row['id'].'">'.$row['name'].'</a></li>';
}
echo '</ul>';
}
}

function CountryGeoTree () {
$country_id=0;
$sql = "SELECT `id`, `country_id`, `name` FROM `geo_tree` WHERE `country_id` = $country_id ORDER BY `name`";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
echo '<ul class="tree">';
while ($row = mysql_fetch_array($result)) {
echo '<li><a href="#country='.$row['id'].'">'.$row['name'].'</a></li>';
CityGeoTree ($row['id']);
}
echo '</ul>';
}
}

function ViewTree ($parent_id) {
$sql = "SELECT `id`, `parent_id`, `name` FROM `catalog_tree` WHERE `parent_id` = $parent_id ORDER BY `id`";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
echo '<ul class="tree">';
while ($row = mysql_fetch_array($result)) {
echo '<li><a href="#view='.$row['id'].'">'.$row['name'].'</a></li>';
CountryGeoTree (0);
}
echo '</ul>';
}
}

function CatalogTree () {
$parent_id=0;
$sql = "SELECT `id`, `parent_id`, `name` FROM `catalog_tree` WHERE `parent_id` = $parent_id ORDER BY `id`";
$result = mysql_query($sql);
if (mysql_num_rows($result) > 0) {
echo '<ul class="tree">';
while ($row = mysql_fetch_array($result)) {

echo '<li><a href="#type='.$row['id'].'">'.$row['name'].'</a></li>';
ViewTree ($row['id']);

}
echo '</ul>';
}
}

CatalogTree ();

вот сделал так, теперь ссылки принимают отдельные значения в виде type=$id; или view=$id; или country=$id; или city=$id;. Как мне теперь склеивать ссылки ввида type=1;view=2;country=2;city=1 то у нас будет Тип1-Вид2-Страна2-Город1. И что бы например если мы просто выделяем тип1 то сслыка была type=1; без вида, страны и города...?

Или я уже не в ту степь забрел???

Link to comment
Share on other sites

  • 0

кстати повтарю свой вопросик оп поводу:

Выход для меня был использовать глобальные переменные (типа global $var;) для функции, но везде пишут что это нельзя использовать, и к тому же на хостинге отключены глобальные переменные register_globals off. Или я что то путаю (переменная global $var; не есть глобальная функция в суперглобальном массиве $GLOBALS)?

Что по этому поводу?

Link to comment
Share on other sites

  • 0
вот сделал так, теперь ссылки принимают отдельные значения в виде type=$id; или view=$id; или country=$id; или city=$id;. Как мне теперь склеивать ссылки ввида type=1;view=2;country=2;city=1 то у нас будет Тип1-Вид2-Страна2-Город1. И что бы например если мы просто выделяем тип1 то сслыка была type=1; без вида, страны и города...?

Или я уже не в ту степь забрел???

формировать перед циклом и пихать в каждый

элемент, а на его основе формировать следкующий)

Что по этому поводу?

Не использовать globals

Link to comment
Share on other sites

  • 0

но если ссылки формировать перед циклом, то они не будут формироваться... :)

там в же цикле собственно и идет перебор ид.

смог склеить ссылки тип и вид, страна и город, а вот склеить вот эти уже не выходит... :)

Link to comment
Share on other sites

  • 0

mario, есть вариант: 4 таблицы + продуманный SQL.

определимся что есть статичная информация, что есть модель взаимосвязей.

Города и Страны - это статичная информация - заносим ее в 2е таблицы и не паримся больше:

Таблица Страны

idс | Name

Таблица Города

cid | idc | Name

Теперь модель взаимосвязей:

Таблица Тип/Подтип

tid | parent_id | Name

Таблица TypeCityMap

mid | tid | parent_id | cid

Выборка

SELECT
TypeCityMap.tid
TypeCityMap.mid,
Города.name,
Страны.name
FROM TypeCityMap
LEFT JOIN Города ON TypeCityMap.cid = Города.cid
LEFT JOIN Страны ON Города.idc = Страны.idc
ORDER BY TypeCityMap.tid, Города.name

результат кладем в ассоциативный двумерный массив 1 c ключом tid:

array (
[tid] array (
[0] array ( mid, city, country )
[1] array ( mid, city, country )
)
)

так как информация типов разнородна то придется сделать еще один запрос (самый нужный)

SELECT *
FROM Тип/Подтип
ORDER BY Тип/Подтип.parent_id DESC, Тип/Подтип.tid DESC

результат кладем в двумерный массив 2 с ключом первой вложенности tid:

array (
[tid] array(
[0] = typename
[1] = parent_id
)
)

далее надо раскидать массив 2 в модель дерева. можно сделать на массиве используя рекурентный вызов функции

модель на массивах (массив 3):

array(
[tid] array( // parent_id то же имеет номер в поле tid
[tid] array(
[tid] array( [пусто] )
)
)

Собственно алгоритм:

идем по массиву 3, беря информацию из массива 2, как только попадаем на "пусто" - обращаемя к массиву 1.

сделать можно, используя рекурентный вызов функции.

PS: зная номер mid таблицы TypeCityMap мы можем собрать нужную цепочку

PPS:

Выход для меня был использовать глобальные переменные (типа global $var;) для функции

не только. см классы РНР

Link to comment
Share on other sites

  • 0

Ну вот и снова выходные и можно сесть за изучение php :)

На досуге подумал, а правильно ли я организовываю базу данных, может она окажется не пригодна для работы? Вообще по каким критериям тут надо смотреть на БД?

на данный момент имею 2 таблицы

одна таблица с Странами и Городами, организована через id; country_id; name. где если country_id=0 То значит это страна :)

вторая таблица с Типами и Видами организована через id; type_id; name. если type_id=0 то значит это тип, а остальное виды типа. :)

И вот тут я почему то начал думать, а вдруг это не слишком удобная таблица, вдруг она окажется не пригодна для работы, ну тут я уже повторяюсь но, все каковы критерии оценки?

И как организовали бы вы?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy