DOC.PROTOTYPES.RU

Главная > Базы данных > Деревья SQL > Nested Sets > практика PHP >

Практика NestedSets - класс PHP управления деревьями Nested Sets, (дополнение)

Введение

Сам класс мы создали в предыдущей статье, но он позволяет только выбирать данные, но не изменять их. Поэтому напишем дополнительные методы.

По структуре и принципу класс такой же как и модуль Perl, единственные отличия в операторах и специфицеских особенностях языка. Итак, функции, которые мы включим в класс:

Схемы и принципы описаны в предыдущих статьях,  поэтому можно смело начинать писать код...

1. Создание (вставка) узла

PHP код (1)
// Создание узла
function InsertUnit ($under = 'root', $tree = 1, $order) {
    if (!is_numeric($under)) {$under = 'root';}
    if (!is_numeric($tree)) {$tree = 1;}
    if ($under == 'root') {
        $level = 1; 
        if ((isset($order) && $order == 'top') || $this->order == 'T') {
            $key = 1;
        } else {
            $sql = 'SELECT MAX('.$this->right.') + 1 AS nums
            FROM '.$this->table.
            ($this->type == 'M' ? ' WHERE '.$this->multi.' = '.$tree : '');
            if (($query = mysql_query($sql)) &&
                (mysql_num_rows($query) == 1) &&
                ($Data = mysql_fetch_array($query))) {$key = $Data['nums'];}
            else {$key = 1;}
        }
    } else {
        $sql = 'SELECT '.$this->left.' AS lk, '.
                         $this->right.' AS rk, '.
                         $this->level.'AS lv'.
                        ($this->type == 'M' ? ', '.$this->multi.' AS cl ' : '').
              ' FROM '.$this->table.' WHERE '.$this->id.' = '.$under;
        if (($mysql_query = mysql_query($sql)) &&
            (mysql_num_rows($mysql_query) == 1) &&
            ($Data = mysql_fetch_array($mysql_query))) {
                $level = $Data['lv'] + 1;
                if ($this->type == 'M') {$tree = $Data['cl'];}
                if ((isset($order) && $order == 'top') || $this->order == 'T') {
                    $key = $Data['cl'];
                }
        } else {trigger_error('ERR! Неправильный ID родительского узла!');}
    }
    $update = 'UPDATE '.$this->table.' SET '.
                    $this->right.' = '.$this->right.' + 2, '.
                    $this->left.' = CASE WHEN '.$this->left.' >= '.$key.
                                       ' THEN '.$this->left.' + 2
                                         ELSE '.$this->left.' END
               WHERE '.$this->right.' >= '.$key.
                   ($this->type == 'M' ? ' AND '.$this->multi.' = '.$tree : '');
    mysql_query($update);
// Список полей 
    $update = 'INSERT INTO '.$this->table.
                ' ('.$this->left.', '.
                     $this->right.', '.
                     $this->level.
                    ($this->type == 'M' ? ', '.$this->multi : '').
             ') VAUES ('.$key.', '.($key + 1).', '.$level.
                    ($this->type == 'M' ? ', '.$tree.')' : ')');
// Выполняем запрос 
    mysql_query($update);
// Получаем идентификатор вставленного узла
    $sql = 'SELECT MAX('.$this->id.') FROM '.$this->table;
    $mysql_query = mysql_query($sql);
    $id = mysql_fetch_array($mysql_query);
    return $id[0];
}

2. Удаление узла

PHP код (2)
// Удаление узла
function DeleteUnit ($unit) {
    if (isset($unit)) {$this->SelectUnit($unit);}
    $skew_tree = $this->unit['right'] - $this->unit['left'] + 1;
    $update = 'DELETE FROM '.$this->table.'
               WHERE '.$this->left.'>='.$this->unit['left'].' AND '.
                       $this->right.'<='.$this->unit['right'].
                       ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : '');
    mysql_query($update);
    $update = 'UPDATE '.$this->table.'
               SET '.$this->left.'= CASE WHEN '.$this->left.'>'.$this->unit['left'].'
                                         THEN '.$this->left.'-'.$skew_tree.'
                                         ELSE '.$this->left.' END, '.
                     $this->right.'='.$this->right.'-'.$skew_tree.
             ' WHERE '.$this->right.'>'.$this->unit['right'].
                      ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : '');
    mysql_query($update);
    return 1;
}

3. Перемещение узла

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

PHP код (3)
// Внутренняя процедура перемещения узла
function _move_unit ($data = array()) {
    if ($data['near'] >= $this->unit['left'] && $data['near'] <= $this->unit['right']) {return 'ERR';}
    $skew_tree = $this->unit['right'] - $this->unit['left'] + 1;
    $skew_level = $data['level_new'] - $this->unit['level'];
// Перемещение вверх по дереву
    if ($this->unit['right'] < $data['near']) {
        $skew_edit = $data['near'] - $this->unit['left'] + 1 - $skew_tree;
        $sql = 'UPDATE '.$this->table.'
                SET '.
                  $this->left.' = CASE WHEN '.$this->right.'<='.$this->unit['right'].' THEN '.
                    $this->left.'+'.$skew_edit.' ELSE CASE WHEN '.$this->left.'>'.$this->unit['right'].' THEN '.
                     $this->left.'-'.$skew_tree.' ELSE '.$this->left.' END END, '.
                  $this->level.' = CASE WHEN '.$this->right.'<='.$this->unit['right'].' THEN '.
                    $this->level.'+'.$skew_level.' ELSE '.$this->level.' END, '.
                  $this->right.' = CASE WHEN '.$this->right.'<='.$this->unit['right'].' THEN '.
                    $this->right.'+'.$skew_edit.' ELSE CASE WHEN '.$this->right.'<='.$data['near'].' THEN '.
                      $this->right.'-'.$skew_tree.' ELSE '.$this->right.' END END
                WHERE '.
                  $this->right.'>'.$this->unit['left'].' AND '.
                  $this->left.'<='.$data['near'].
                ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : '');
        $mysql_query = mysql_query($sql);
    } else {
// Перемещение вниз по дереву
        $skew_edit = $data['near'] - $this->unit['left'] + 1;
        $sql = 'UPDATE '.$this->table.'
                SET '.
                  $this->right.' = CASE WHEN '.$this->left.'>='.$this->unit['left'].' THEN '.
                    $this->right.'+'.$skew_edit.' ELSE CASE WHEN '.$this->right.'<'.$this->unit['left'].' THEN '.
                      $this->right.'+'.$skew_tree.' ELSE '.$this->right.' END END, '.
                  $this->level.' = CASE WHEN '.$this->left.'>='.$this->unit['left'].' THEN '.
                    $this->level.'+'.$skew_level.' ELSE '.$this->level.' END, '.
                  $this->left.' = CASE WHEN '.$this->left.'>='.$this->unit['left'].' THEN '.
                    $this->left.'+'.$skew_edit.' ELSE CASE WHEN '.$this->left.'>'.$data['near'].' THEN '.
                      $this->left.'+'.$skew_tree.' ELSE '.$this->left.' END END
                WHERE '.
                  $this->right.'>'.$data['near'].' AND '.
                  $this->left.'<'.$this->unit['right'].
                  ($this->type == 'M' ? ' AND '.$this->multi.'='.$this->unit['multi'] : '');
        $mysql_query = mysql_query($sql);
    }
    return 'OK';
}

 

Продолжение следует...

Сергей Томулевич aka Phoinix (01.06.2005 г.)

Еще статьи по теме:

Valid HTML 4.01 Transitional
Copyright © 2011 Сергей Томулевич