Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не получается перемещать ветви в nested sets 
:(
    Опции темы
Cache
Дата 19.9.2011, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 6.11.2007

Репутация: нет
Всего: нет



Здравствуйте!
Есть класс для работы с NS, взятый отсюда 
Привожу код:
Код

<?php defined('SYSPATH') or die('No direct script access.');

/*
CREATE TABLE `tree` (
    `id` INT(10) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(255) NOT NULL,
    `left_key` INT(10) NOT NULL,
    `right_key` INT(10) NOT NULL,
    `level` INT(10) NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `key` (`left_key`, `right_key`, `level`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
*/

class NSTree
{
    protected $table = NULL;

    public function __construct($tablename)
    {
        $this->table = $tablename;
    }

    // Модифицирует ключи
    protected function modifyNodes($key, $delta)
    {
        $query =
            'UPDATE '.Database::instance()->quote_table($this->table).'
            SET right_key = right_key + '.(int)$delta.'
            WHERE right_key >= '.(int)$key;
        DB::query(Database::UPDATE, $query)->execute();

        $query =
            'UPDATE '.Database::instance()->quote_table($this->table).'
            SET left_key = left_key + '.(int)$delta.'
            WHERE left_key >= '.(int)$key;
        DB::query(Database::UPDATE, $query)->execute();
    }

    public function getNode($id)
    {
        $result = DB::select()
        ->from($this->table)
        ->where('id', '=', $id)
        ->execute();

        if (count($result) == 0)
            throw new Exception('Node id='.$id.' does not exist.');

        return $result->current();
    }

    public function clear($extrafields=array())
    {
        if (!is_array($extrafields))
            throw new Exception('$extrafields must be array.');
        
        DB::query(NULL, 'TRUNCATE '.Database::instance()->quote_table($this->table))->execute();

        DB::delete($this->table)->execute();

        $data = array(
            'id' => 1,
            'name' => '<root>',
            'left_key' => 1,
            'right_key' => 2,
            'level' => 0
        );
        $data = $data + $extrafields;
        list($insert_id, $tmp) = DB::insert($this->table, array_keys($data))->values(array_values($data))->execute();

        return $insert_id;
    }

    public function getTree($id=NULL)
    {
        $id = (int) $id;
        $QTblName = Database::instance()->quote_table($this->table);

        if ($id != 0)
        {
            $node = $this->getNode($id);

            $query =
                'SELECT *
                FROM '.$QTblName.'
                WHERE left_key >= '.(int)$node['left_key'].' AND right_key <= '.(int)$node['right_key'].'
                ORDER BY left_key';
        }
        else
        {
            $query =
                'SELECT *
                FROM '.$QTblName.'
                ORDER BY left_key';
        }

        $result = DB::query(Database::SELECT, $query)->execute();

        return $result;
    }

    public function getPath($id)
    {
        $node = $this->getNode($id);

        $query =
            'SELECT *
            FROM '.Database::instance()->quote_table($this->table).'
            WHERE right_key > '.(int)$node['left_key'].' AND left_key < '.(int)$node['right_key'].'
            ORDER BY left_key';

        $result = DB::query(Database::SELECT, $query)->execute();

        return $result;
    }

    public function insert($id, $extrafields=array())
    {
        if (!is_array($extrafields))
            throw new Exception('$extrafields must be array.');

        // Находим родителя
        $parent = $this->getNode($id);

        DB::query(NULL, 'START TRANSACTION')->execute();

        // Обновляем ключи существующего дерева, узлы стоящие за родительским узлом
        $this->modifyNodes((int)$parent['right_key'], 2);
        
        // Добавляем новый узел
        $node = array(
            'id' => NULL,
            'left_key' => $parent['right_key'],
            'right_key' => $parent['right_key'] + 1,
            'level' => $parent['level'] + 1
        );
        $node = $node + $extrafields;
        list($insert_id, $tmp) = DB::insert($this->table, array_keys($node))->values(array_values($node))->execute();

        DB::query(NULL, 'COMMIT')->execute();
        
        return $insert_id;
    }

    // Метод перемещает ноду $id в родительскую ноду $parentId
    public function move($id)
    {
        $node = $this->getNode($id);

        DB::query(NULL, 'START TRANSACTION')->execute();

        // Удаляем узел (вместе с веткой)
        $query =
            'DELETE FROM '.Database::instance()->quote_table($this->table).'
            WHERE left_key >= '.(int)$node['left_key'].' AND right_key <= '.(int)$node['right_key'];
        DB::query(Database::DELETE, $query)->execute();

        $width = $node['right_key'] - $node['left_key'] + 1;
        // Обновление последующих узлов
        $this->modifyNodes((int)$node['right_key'], -$width);

        DB::query(NULL, 'COMMIT')->execute();
    }

    public function mymove($id, $target, $after = true)
    {
        $node = $this->getNode($id);
        $targetnode = $this->getNode($target);
        $arr['node']=$node;
        $arr['target']=$targetnode;
        $arr['action_after']='true';
        if (!$after) $arr['action_after']='false';
        
        return $arr;
        
    }


    public function delete($id)
    {
        $node = $this->getNode($id);

        DB::query(NULL, 'START TRANSACTION')->execute();

        // Удаляем узел (вместе с веткой)
        $query =
            'DELETE FROM '.Database::instance()->quote_table($this->table).'
            WHERE left_key >= '.(int)$node['left_key'].' AND right_key <= '.(int)$node['right_key'];
        DB::query(Database::DELETE, $query)->execute();

        $width = $node['right_key'] - $node['left_key'] + 1;
        // Обновление последующих узлов
        $this->modifyNodes((int)$node['right_key'], -$width);

        DB::query(NULL, 'COMMIT')->execute();
    }

    public function check($thorough=FALSE)
    {
        $QTblName = Database::instance()->quote_table($this->table);

        // Тест 1
        $query =
            'SELECT id
            FROM '.$QTblName.'
            WHERE MOD(right_key - left_key, 2) = 0';
        $result = DB::query(Database::SELECT, $query)->execute();

        if (count($result) != 0)
            throw new Exception('Test 1 integrity check failed.');
        
        // Тест 2
        $query =
            'SELECT id
            FROM '.$QTblName.'
            WHERE MOD(left_key - level + 2, 2) = 0';
        $result = DB::query(Database::SELECT, $query)->execute();

        if (count($result) != 0)
            throw new Exception('Test 2 integrity check failed.');

        // Тест 3
        if ($thorough)
        {
            $query =
                'SELECT t1.id, COUNT(t1.id) AS rep, MAX(t3.right_key) AS max_right
                FROM
                    '.$QTblName.' AS t1,
                    '.$QTblName.' AS t2,
                    '.$QTblName.' AS t3
                WHERE
                    t1.left_key <> t2.left_key
                  AND
                    t1.left_key <> t2.right_key
                  AND
                    t1.right_key <> t2.left_key
                  AND
                    t1.right_key <> t2.right_key
                GROUP BY
                    t1.id
                HAVING
                    max_right <> SQRT( 4 * rep + 1 ) + 1';

            $result = DB::query(Database::SELECT, $query)->execute();

            if (count($result) != 0)
                throw new Exception('Test 3 integrity check failed.');
        }

        // Тест 4, проверка level
        $query =
            'SELECT node.id as id, node.level as level
            FROM
                '.$QTblName.' AS node,
                '.$QTblName.' AS parent
            WHERE node.left_key BETWEEN parent.left_key AND parent.right_key
            GROUP BY node.id
            HAVING COUNT(parent.name) - 1 != level
            ORDER BY node.left_key';
        
        $result = DB::query(Database::SELECT, $query)->execute();

        if (count($result) != 0)
            throw new Exception('Test 4 integrity check failed.');

    }
}

Суть проблемы - функция move() должна перемещать ветви, но вместо этого - она их удаляет smile
В функцие mymove($id, $target, $after = true) я хочу написать нормальное перемещение, параметры функции - $id (элемент для переноса), $target (элемент, рядом с которым нужно поставить перемещаемый элемент), $after (если тру - вставить после $target, если false - до) = true
Помогите, пожалуйста, с самой логикой - как переместить ветвь и всех ее детишек в другое место? Нужно ли при этом менять id переносимой ветви? И в БД все ли id должны идти по  порядку или может быть так - 1 2 .. 4 5?
Спасибо!
PM MAIL   Вверх
MoLeX
Дата 19.9.2011, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140





--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0789 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.