Nested удаление дерева, как пересчитывать lft, rgt?

Коллеги, добрый вечер!
Удаляю ветку целиком.

Вот так

/**
     * @param $node
     * @return void
     */
    public function removeTree(Service $node)
    {
        $this->createQueryBuilder("s")
            ->delete()
            ->where("s.lft = :lft")->setParameter("lft", $node->getLft())
            ->andWhere("s.rgt = :rgt")->setParameter("rgt", $node->getRgt())
            ->andWhere("s.root = :root")->setParameter("root", $node->getRoot())
            ->getQuery()
            ->execute();
    }


Всё прекрасно удаляется, вот только как теперь пересчитать lft, rgt?

Когда я создаю ноды, индексы пересчитываются, но в большую сторону.

5db3244ebd8c1638593133.png

5db32467cf841968588652.png

Использую
  • Вопрос задан
  • 160 просмотров
Решения вопроса 1
IgorPI
@IgorPI Автор вопроса
Решение.
В первом приближении, пересчитываю следующим образом.

class ServiceRepository extends NestedTreeRepository
{
...
/**
     * @param Service $node
     * @return void
     * @throws ORMException
     * @throws OptimisticLockException
     */
    public function removeTree(Service $node)
    {
        $this->createQueryBuilder("s")
            ->delete()
            ->where("s.lft >= :lft")->setParameter("lft", $node->getLft())
            ->andWhere("s.rgt <= :rgt")->setParameter("rgt", $node->getRgt())
            ->andWhere("s.root = :root")->setParameter("root", $node->getRoot())
            ->getQuery()
            ->execute();

        $em = $this->getEntityManager();
        $em->beginTransaction();
        $repository = $em->getRepository("App:Service");
        $refreshLeftAndRight = function($root, $left) use ($repository, &$refreshLeftAndRight) {
            $right = $left + 1;
            $children = $repository->findBy(['parent' => $root,]);

            foreach ($children as $entity) {
                $right = $refreshLeftAndRight($entity, $right);
            }
            $root->setlft($left);
            $root->setRgt($right);
            return $right + 1;
        };

        foreach ($repository->findBy(["parent" => null]) as $rootEntry) {
            $refreshLeftAndRight($rootEntry, 1);
        }

        $em->flush();
        $em->commit();
    }

...


Кто в теме тот поймет что здесь, происходит.
Конечно не идеально.
В будущем стоит пересчитывать только те корневые ветки, в которых произошло удаление.
В этом случае мы пересчитываем всё.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Доброе время дня.
Для реализации дерева есть готовый бандл расширений для доктрины.
Посмотрите, может использовать готовое решение проще.
Ответ написан
Ваш ответ на вопрос

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

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