Спасибо, покопаю в этом направлении. Потом по результату отпишусь в каком месте был балбесом :)
function MoveAll($ID, $newParentId, $condition = '') { $node_info = $this->GetNodeInfo($ID); if (FALSE === $node_info) { return FALSE; } list($leftId, $rightId, $level) = $node_info; $node_info = $this->GetNodeInfo($newParentId); if (FALSE === $node_info) { return FALSE; } list($leftIdP, $rightIdP, $levelP) = $node_info; if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId) || ($level == $levelP+1 && $leftId > $leftIdP && $rightId < $rightIdP)) { $this->ERRORS_MES[] = extension_loaded('gettext') ? _('cant_move_tree') : 'cant_move_tree'; return FALSE; } if (!empty($condition)) { $condition = $this->_PrepareCondition($condition); } if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level - 1) { $sql = 'UPDATE ' . $this->table . ' SET ' . $this->table_level . ' = CASE WHEN ' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_level.sprintf('%+d', -($level-1)+$levelP) . ' ELSE ' . $this->table_level . ' END, ' . $this->table_right . ' = CASE WHEN ' . $this->table_right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) . ' THEN ' . $this->table_right . '-' . ($rightId-$leftId+1) . ' ' . 'WHEN ' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_right . '+' . ((($rightIdP-$rightId-$level+$levelP)/2)*2+$level-$levelP-1) . ' ELSE ' . $this->table_right . ' END, ' . $this->table_left . ' = CASE WHEN ' . $this->table_left . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) . ' THEN ' . $this->table_left . '-' . ($rightId-$leftId+1) . ' ' . 'WHEN ' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_left . '+' . ((($rightIdP-$rightId-$level+$levelP)/2)*2+$level-$levelP-1) . ' ELSE ' . $this->table_left . ' END ' . 'WHERE ' . $this->table_left . ' BETWEEN ' . ($leftIdP+1) . ' AND ' . ($rightIdP-1); } elseif ($leftIdP < $leftId) { $sql = 'UPDATE ' . $this->table . ' SET ' . $this->table_level . ' = CASE WHEN ' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_level.sprintf('%+d', -($level-1)+$levelP) . ' ELSE ' . $this->table_level . ' END, ' . $this->table_left . ' = CASE WHEN ' . $this->table_left . ' BETWEEN ' . $rightIdP . ' AND ' . ($leftId-1) . ' THEN ' . $this->table_left . '+' . ($rightId-$leftId+1) . ' ' . 'WHEN ' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_left . '-' . ($leftId-$rightIdP) . ' ELSE ' . $this->table_left . ' END, ' . $this->table_right . ' = CASE WHEN ' . $this->table_right . ' BETWEEN ' . $rightIdP . ' AND ' . $leftId . ' THEN ' . $this->table_right . '+' . ($rightId-$leftId+1) . ' ' . 'WHEN ' . $this->table_right . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_right . '-' . ($leftId-$rightIdP) . ' ELSE ' . $this->table_right . ' END ' . 'WHERE (' . $this->table_left . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId. ' ' . 'OR ' . $this->table_right . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId . ')'; } else { $sql = 'UPDATE ' . $this->table . ' SET ' . $this->table_level . ' = CASE WHEN ' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_level.sprintf('%+d', -($level-1)+$levelP) . ' ELSE ' . $this->table_level . ' END, ' . $this->table_left . ' = CASE WHEN ' . $this->table_left . ' BETWEEN ' . $rightId . ' AND ' . $rightIdP . ' THEN ' . $this->table_left . '-' . ($rightId-$leftId+1) . ' ' . 'WHEN ' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_left . '+' . ($rightIdP-1-$rightId) . ' ELSE ' . $this->table_left . ' END, ' . $this->table_right . ' = CASE WHEN ' . $this->table_right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) . ' THEN ' . $this->table_right . '-' . ($rightId-$leftId+1) . ' ' . 'WHEN ' . $this->table_right . ' BETWEEN ' . $leftId . ' AND ' . $rightId . ' THEN ' . $this->table_right . '+' . ($rightIdP-1-$rightId) . ' ELSE ' . $this->table_right . ' END ' . 'WHERE (' . $this->table_left . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP . ' ' . 'OR ' . $this->table_right . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP . ')'; } $sql .= $condition; $this->db->StartTrans(); $res = $this->db->Execute($sql); if (FALSE === $res) { $this->ERRORS[] = array(2, 'SQL query error.', __FILE__ . '::' . __CLASS__ . '::' . __FUNCTION__ . '::' . __LINE__, 'SQL QUERY: ' . $sql, 'SQL ERROR: ' . $this->db->ErrorMsg()); $this->ERRORS_MES[] = extension_loaded('gettext') ? _('internal_error') : 'internal_error'; $this->db->FailTrans(); return FALSE; } $this->db->CompleteTrans(); return TRUE; }
То есть то что я показал должно работать? :)
Может там надо как то переструктурировать после МувОл() еще одним запросом?
Вообще мне как то эта избыточность не нравиться очень, id-parent_id ну будет лучше, если дерево генериться только в админке (допустим под каждый модуль своя база т. е. категории, магазин, а дети категорий, соответственно в отдельных базах лежат и так же parent_id у них равен id у базы категорий) и при выводе карты сайта.
Если глубина не больше 4, ну край, 5 уровней, а категорий в базе не больше 1000 (вообще не больше 100 по идее) есть ли смысл в nested sets?
ze6ra добавил 14.09.2011 в 11:14
Весь метод редактирования статьи (со всей его кривизной):
function edit(){ if (!$this->_auth->access('edit_category')) $this->no_access(); $table = $this->param(0); $id = $this->param(1); if (($table != '' and !is_numeric($table)) and ($id != '' and is_numeric($id))) { $row = $this->_model->get_row($table, $table . "_id=" . sql($id)); require_once(DIR_FW . 'libs' . DS . 'dbtree.php'); $this->_dbtree = new dbtree($table, $table, $this->_model); $tree = $this->_dbtree->Full(''); $parent_info = $this->_dbtree->GetParentInfo($id); #Array to edit $insert = $row; $insert[$table . '_url'] = post(urldecode($table . '_url')); $insert[$table . '_title'] = post($table . '_title'); $insert[$table . '_seo_title'] = post($table . '_seo_title'); $insert[$table . '_content'] = post($table . '_content'); $insert[$table . '_description'] = post($table . '_description'); $insert[$table . '_seo_description'] = post($table . '_seo_description'); $msg_error = ""; if (post($table . '_title') != "" or post($table . '_url') != "") { if (trim(post($table . '_title')) == "") $msg_error .= "Не введено название.<br />"; if (trim(post($table . '_url')) == "" or "" != $this->_model->get_result($table, $table . "_url", $table . "_url=" . sql(post('url')) . " AND " . $table . "_id!=" . sql($id, 'num'))) $msg_error .= "Не введен url статьи или этот url уже занят.<br />"; if ($msg_error == "") { if($msg_error == "" and $parent_info[$table . "_id"] != post($table . '_parent_id')) //echo "Parent has changed!"; $this->_dbtree->MoveAll($id, post($table . '_parent_id'), ''); //echo($parent_info[$table . "_id"]); //p($_POST); $this->_model->edit_structure_row($table, $insert, $id); redirect("admin/structure/" . $table); } } $this->_view->load_page("edit/categories"); $this->_common(); $this->_view->setvar("msg_error", isset($msg_error) ? $msg_error : ""); $this->_view->setvar("item", $row); #Categories tree generation if (!empty($this->_dbtree->ERRORS_MES)) { echo 'DB Tree Error!<pre>'; print_r($this->_dbtree->ERRORS_MES); if (!empty($this->_dbtree->ERRORS)) { print_r($this->_dbtree->ERRORS); } echo '</pre>'; exit; } else { while ($structure_tree = $this->_dbtree->NextRow()) { $structure_tree['spacer'] = str_repeat(' ', 1 * $structure_tree[$table . '_level']); $sections[] = $structure_tree; $this->_view->clean("selected"); if ($structure_tree[$table . '_id'] == $parent_info[$table . '_id']) {$this->_view->parse("selected");} if ($structure_tree[$table . '_id'] != $id) { $this->_view->setvar("block", $structure_tree); $this->_view->parse($table . "_structure"); } } } $this->_view->setvar("pid", $parent_info[$table . '_id']); $this->_view->render();
Очень плохо это потеря пары десятков зеленых тысяч за прошлый вечер. Кейвеб лежал 14 часов. Собственно набежало.
При зеркалировании отставание одной базы от другой на минуту опять же может принести убытки при переключении. TTL, да, минута.
Я и пытаюсь выяснить куда лучше разнести два зеркала, в германии пинги хорошие и по ценам хорошо.
Хорошо бы конечно сразу с ресселлерами, вод где теперь реселлера грейтвеба найти, раз он такой хороший? Просто с оплатой проблемы возникнут, если напрямую, - по безналу же надо.
То есть два голоса за лизвеб? Хетзнер не так хорош выходит? Знакомые большие проекты, так же чувствительные к падениям, снимают несколько серверов именно у второго, говорят, за два года проблем не было.
Кому верить?
ze6ra добавил 10.09.2011 в 23:07
Все просто, забили на бекапы. Работать умеют но не без человеческого фактора в виде поху... кхм... халатности.
ze6ra добавил 10.09.2011 в 23:11
Кейвеб к слову лежит уже восемь часов, данные не забрать. Может у них там революция или забастовка, как хостер они уже наверно мертвы к завтрашнему дню будут.
Или решили годовой аптайм за сутки до 98% прижать :)
ДЦ германского Hetzner как? Просто были у кей-мать-его-веба. И теперь страшно в германию лезть (а пинг у них прекрасный в германии конечно)
Оперативно обменял вмр на яд, всем очень доволен. Спасибо!
Нас завоевала Эстония? Слово «скоро» уже неприменимо к данной ситуации :/
Возможен небольшой текст нужной тематики, насыщеный тематическими ссылками. Символов 250-350.
Спасибо огроменное, а я, балда, пробовал f.cat.selectedIndex и зачем то объект из массива приписывал (f.cat.selectedIndex[0]) 😂