Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > Дублирование древовидной структуры в таблице


Автор: Kefir 14.2.2006, 23:43
Столкнулся с проблемой. Пока что не знаю как решать. В таблице БД у меня хранится дерево страниц сайта в виде:
Код
id | parent_id | title | language
1    0           "T1"     0
2    0           "T2"     0
3    1           "Sub1"   0
4    1           "Sub2"   0
5    4           "Sub3"   0
.... etc etc etc

Т.е. в parent_id хранится номер старшей (родительской) страницы. Если parent_id = 0, то это корневая станичка. Со временем понадобилось добавление языков. Проблемы начались с фичей "скопировать структуру из другого языка" - т.е. при добавлении языка в БД автоматически добавляется вся структура выбранного пользователем языка (дублируется с тем лишь отличием, что id языка меняется со старого на только что созданный). Сначала я было ринулся делать всё это дело так:
Код

INSERT INTO `pages` (parent_id, title, language)
SELECT parent_id, title, $new_lang_id AS language FROM `pages` WHERE language=$autofill_lang_donor

И всё бы ничего (всё прекрасно добавлялось), только вот проблема появилась - парент_ид нельзя так в наглую копировать - структура сразу ломается. его надо заново генерировать.

Я очень надеюсь, что эту мою бредятину хоть кто-нибудь поймёт и посоветует как решить эту проблему.

Автор: Gold Dragon 15.2.2006, 09:25
прости, но понял что нужно smile

Что должно получится на выходе?

Автор: Kefir 15.2.2006, 10:44
Ок. Сейчас постараюсь поподробнее написать.
Код
id | parent_id | title | language
1    0          "Page1"  0
2    0          "Page2"  0
3    1          "Page3"  0
4    1          "Page4"  0
5    3          "Page5"  0
6    3          "Page6"  0
7    3          "Page7"  0
8    2          "Page8"  0
9    2          "Page9"  0
10   2          "Page10" 0

Это древовидная структура стайта. language равен 0 - это значит, что эти странички на, допустим, русском языке. Если зарисовать структуру по другому, то будет так:
Код

Page1
 - Page3
    - Page5
    - Page6
    - Page7
 - Page4 
Page2
 - Page8
 - Page9
 - Page10


Идём дальше. Редактор сайта должен иметь возможность добавлять языки. Причём при добавлении языка ему задаётся вопрос - "продублировать структуру из другого языка?" и если да, то из какого. Допустим он добавил английский язык (id = 1) и сказал продублировать структуру из русского языка. Тогда к первой таблице в начале поста должны прибавится следующие записи:
Код

id | parent_id | title | language
11   0          "Page1"  1
12   0          "Page2"  1
13   11         "Page3"  1
14   11         "Page4"  1
15   13         "Page5"  1
16   13         "Page6"  1
17   13         "Page7"  1
18   12         "Page8"  1
19   12         "Page9"  1
20   12         "Page10" 1

Т.е. надо сдублировать записи с language=0 и проставить в них language=1 + переделывать parent_id, т.к. в противном случае записи с английским языком будут ссылаться на родительскую запись из русского языка.

Очень надеюсь, что стало попонятнее.

Автор: Gold Dragon 16.2.2006, 09:25
Kefir,
понятно стало до жути smile

а теперь по структуре... А не проще тупо добавить ещё один столбец, т.е.общий ID

Код

id    s_id    parent_id    pages    language
1    1    0    Pages 1    0
2    2    0    Pages 2    0
3    3    1    Pages 3    0
4    4    1    Pages 4    0
5    5    3    Pages 5    0
6    6    2    Pages 6    0
7    7    2    Pages 7    0
8    1    0    Pages 1    1
9    2    0    Pages 2    1
10    3    1    Pages 3    1
11    4    1    Pages 4    1
12    5    3    Pages 5    1
13    6    2    Pages 6    1
14    7    2    Pages 7    1



и тогда всё отлично получается
Код

Язык 0

Pages 1
   Pages 3
      Pages 5
   Pages 4
Pages 2
   Pages 6
   Pages 7
---------------------------------------

Язык 1

Pages 1
   Pages 3
      Pages 5
   Pages 4
Pages 2
   Pages 6
   Pages 7





Автор: Kefir 16.2.2006, 16:14
Gold Dragon, дело в том, что структура разных языков может быть различна и если юзер захочет привязать новую страничку к этому пролю - то получится ещё дополнительная работа (или я просто не понял твою идею).
Вообще, решение я сделал такое, может можно его оптимизировать, но главное - работает:
Код
$q = "SELECT * FROM `".DB_TBL_PAGES."` WHERE language=".$autofill; // сначала выберем все страницы на копируемом языке
$res = mysql_query($q, $this->db_link);
$n = mysql_num_rows($res);
// тут будем хранить старые и новые ПИДы в виде "старый пид" -> "новый пид":
$update_pid = array();
$lang_id = count($lang)-1; // $lang - массив языков, в $lang_id получаем ИД только что созданного (последнего) языка
// в цикле идёт заполнение таблицы и массива $update_pid
for($i = 0; $i < $n; $i++) {
    $r = mysql_fetch_assoc($res);
    $q = "INSERT INTO `".DB_TBL_PAGES."` (...) VALUES(/* значения из $r и ставим правильный ИД языка. пид не трогаем. */)";
    mysql_query($q, $this->db_link);
    $last = mysql_fetch_assoc(mysql_query("SELECT id AS last_id FROM `".DB_TBL_PAGES."` ORDER BY id DESC LIMIT 1")); // получаем последний ИД странички
    $update_pid += array($r['id'] => $last['last_id']); // пополняем список ПИДов, которые надо заменить
}
foreach($update_pid as $k => $v) {
    // для каждой пары ПИДов обновляем инфу в БД
    $q = "UPDATE `".DB_TBL_PAGES."` SET parent_id=".$v." WHERE parent_id=".$k." AND language=".$lang_id;
    mysql_query($q, $this->db_link);
}

Вот. Ничего более простого в голову не пришло.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)