muhammad_97
@muhammad_97
PHP-разработчик

Перемещение ветки Nested Set в Laravel?

Добрый вечер. Пытаюсь перенести ветку NS по этой статье: www.getinfo.ru/article610.html.

Для начала выберем ключи следующих узлов:

1. Ключи и уровень перемещаемого узла;

SELECT level, left_key, right_key FROM my_tree WHERE id = $id


Это я делаю так:

public function move($parentId, $leftSibling = null)


Category::find(195)->move(199);

. где 195 - id перемещаемого узла, 199 - id нового родителя.

2. Уровень нового родительского узла (если узел перемещается в "корень" то сразу можно подставить значение 0):

SELECT level FROM my_tree WHERE id = $id_up

Получаем $level_up


Выбираю родителя целиком:

$parent = self::find($parentId);

3. Правый ключ узла за который мы вставляем узел (ветку):


Делаю это так:

if ($this->parentNode()->id == $parent->id)
		{
			if ($parent->hasChild())
			{
				if ($leftSibling === null)
				{
					throw Exception('Sibling not found');
				}

				$rightKeyNear = $leftSibling->right_key;
			}
			else
			{
				$rightKeyNear = $parent->left_key;
			}
		}
		else
		{
			if ($parent->level == 0)
			{
				//перемещение в корень
				$rightKeyNear = self::max('right_key')->get();
			}
			else
			{
				$rightKeyNear = $parent->right_key - 1;
			}
		}


4. Определяем смещения:

$level_up - $level + 1 = $skew_level - смещение уровня изменяемого узла;
$right_key - $left_key + 1 = $skew_tree - смещение ключей дерева;


У меня $keySkew вместо $skew_tree:

$levelSkew = $parent->level - $this->level + 1;
$keySkew = $this->right_key - $this->left_key + 1;


Выбираем все узлы перемещаемой ветки:

SELECT id FROM my_tree WHERE left_key >= $left_key AND right_key <= $right_key

Получаем $id_edit - список id номеров перемещаемой ветки.


$childIds = self::where('left_key', '>=', $this->left_key)->where('right_key', '<=', $this->right_key)->lists('id');


Так же требуется определить: в какую область перемещается узел, для этого сравниваем $right_key и $right_key_near, если $right_key_near больше, то узел перемещается в облась вышестоящих узлов, иначе - нижестоящих (почему существует разделение описано ниже).

if ($rightKeyNear > $this->right_key)
		{
			echo 'up';
			$editSkew = $rightKeyNear - $this->left_key + 1;

			// UPDATE my_tree SET right_key = right_key + $skew_tree WHERE right_key < $left_key AND right_key > $right_key_near
			self::where('right_key', '<', $this->left_key)->where('right_key', '>', $rightKeyNear)->update(array('right_key' => DB::raw('`right_key` + (' . $keySkew . ')')));
	
			// UPDATE my_tree SET left_key = left_key + $skew_tree WHERE left_key < $left_key AND left_key > $right_key_near
			self::where('left_key', '<', $this->left_key)->where('left_key', '>', $rightKeyNear)->update(array('left_key' => DB::raw('`left_key` - (' . $keySkew . ')')));
			
		}
		else
		{
			echo 'down';
			$editSkew = $rightKeyNear - $this->left_key - $keySkew + 1;

			// UPDATE my_tree SET right_key = right_key - $skew_tree WHERE right_key > $right_key AND right_key <= $right_key_near
			self::where('right_key', '>', $this->right_key)->where('right_key', '<=', $rightKeyNear)->update(array('right_key' => DB::raw('`right_key` - (' . $keySkew . ')')));
		
			// UPDATE my_tree SET left_key = left_key - $skew_tree WHERE left_key < $left_key AND left_key > $right_key_near
			self::where('left_key', '<', $this->left_key)->where('left_key', '>', $rightKeyNear)->update(array('left_key' => DB::raw('`left_key` - (' . $keySkew . ')')));
		}


// UPDATE my_tree SET left_key = left_key + $skew_edit, right_key = right_key + $skew_edit, level = level + $skew_level WHERE id IN ($id_edit)
		self::whereIn('id', $childIds)->update(array('left_key' => DB::raw('`left_key` + (' . $editSkew . ')'), 'right_key' => DB::raw('`right_key` + (' . $editSkew . ')'), 'level' => DB::raw('`level` + (' . $levelSkew . ')')));


Код целиком: pastebin.com/t9BJ2tDr

Проблема в том, что ветка почему-то не перемещается. Пожалуйста, укажите на ошибки.
  • Вопрос задан
  • 824 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы