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

Использую
  • Вопрос задан
  • 166 просмотров
Решения вопроса 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
Доброе время дня.
Для реализации дерева есть готовый бандл расширений для доктрины.
Посмотрите, может использовать готовое решение проще.
Ответ написан
Ваш ответ на вопрос

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

Похожие вопросы