0

我在 Symofny4 应用程序中使用 (Atlantic18/DoctrineExtensions) Gedmo 嵌套集树策略管理类别。

我需要重新排序现有的树,将一组重新排列的类别传递给我的控制器。

所以起始树是

- (1) Senza Categoria (2)
- (1) Utenze (6)
-- (2) Gas (3)
-- (4) Energia (5)

启动数据库表 在此处输入图像描述

定义新订单的数组是这样的

[
  [
    "icona" => "fas fa-ban"
    "nome" => "Senza categoria"
    "id" => "1"
  ]
  [
    "icona" => "far fa-copy"
    "nome" => "Utenze"
    "id" => "2"
    "children" => [
      [
        "icona" => "fas fa-plug"
        "nome" => "Energia"
        "id" => "4"
      ]
      [
        "icona" => "fab fa-gripfire"
        "nome" => "Gas"
        "id" => "3"
      ]
    ]
  ]
]

所以预期的树是

- (1) Senza Categoria (2)
- (1) Utenze (6)
-- (2) Energia (3)
-- (4) Gas (5)

类别实体

namespace App\Entity\Contabilita\Spese;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 *
 * @Gedmo\Tree(type="nested")
 * @ORM\Table(name="categoria_spesa")
 * @ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository")
 */
class Categoria
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    private $nome;

    /**
     * @ORM\Column(type="string", length=50, nullable=true)
     */
    private $icona;

    /**
     * @Gedmo\TreeLeft
     * @ORM\Column(name="lft", type="integer")
     */
    private $lft;

    /**
     * @Gedmo\TreeLevel
     * @ORM\Column(name="lvl", type="integer")
     */
    private $lvl;

    /**
     * @Gedmo\TreeRight
     * @ORM\Column(name="rgt", type="integer")
     */
    private $rgt;

    /**
     * @Gedmo\TreeRoot
     * @ORM\ManyToOne(targetEntity="Categoria")
     * @ORM\JoinColumn(name="tree_root", referencedColumnName="id", onDelete="CASCADE")
     */
    private $root;

    /**
     * @Gedmo\TreeParent
     * @ORM\ManyToOne(targetEntity="Categoria", inversedBy="sottocategorie")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $parent;

    /**
     * @ORM\OneToMany(targetEntity="Categoria", mappedBy="parent")
     * @ORM\OrderBy({"lft" = "ASC"})
     */
    private $sottocategorie;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Contabilita\Spese\Spesa", mappedBy="categoria", fetch="EXTRA_LAZY")
     */
    private $spese;

    /**
     * Categoria constructor.
     */
    public function __construct()
    {
        $this->sottocategorie = new ArrayCollection();
        $this->spese = new ArrayCollection();
    }

    /**
     * @return int|null
     */
    public function getId(): ?int
    {
        return $this->id;
    }

    /**
     * @return string|null
     */
    public function getNome(): ?string
    {
        return $this->nome;
    }

    /**
     * @param string $nome
     *
     * @return $this
     */
    public function setNome(string $nome): self
    {
        $this->nome = $nome;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getIcona(): ?string
    {
        return $this->icona;
    }

    /**
     * @param string|null $icona
     *
     * @return $this
     */
    public function setIcona(?string $icona): self
    {
        $this->icona = $icona;

        return $this;
    }

    /**
     * @return Collection|Spesa[]
     */
    public function getSpese(): Collection
    {
        return $this->spese;
    }

    /**
     * @param Spesa $spese
     *
     * @return $this
     */
    public function addSpese(Spesa $spese): self
    {
        if (!$this->spese->contains($spese)) {
            $this->spese[] = $spese;
            $spese->setCategoria($this);
        }

        return $this;
    }

    /**
     * @param Spesa $spese
     *
     * @return $this
     */
    public function removeSpese(Spesa $spese): self
    {
        if ($this->spese->contains($spese)) {
            $this->spese->removeElement($spese);
            // set the owning side to null (unless already changed)
            if ($spese->getCategoria() === $this) {
                $spese->setCategoria(null);
            }
        }

        return $this;
    }

    /**
     * @return Categoria
     */
    public function getRoot(): Categoria
    {
        return $this->root;
    }

    /**
     * @return Categoria|null
     */
    public function getParent(): ?Categoria
    {
        return $this->parent;
    }

    /**
     * @param mixed $parent
     *
     * @return Categoria
     */
    public function setParent($parent)
    {
        $this->parent = $parent;
        return $this;
    }
}

在我的控制器中,我有一个递归函数试图达到我的目标,一个 JS 调用更新函数传递类别作为参数

public function update(Request $request)
{
  if(!$request->isXmlHttpRequest()){
      throw $this->createAccessDeniedException('What are you triyng to do?');
  }

  $categorie = $request->get('categorie');

  $em = $this->getDoctrine()
      ->getManager();

  $repository = $em->getRepository(Categoria::class);

  // Starts the reorder
  $this->reorderCategorie(null, $categorie, $repository);
  $em->flush();

  return $this->json(['status' => 1, 'message' => 'Ok']);
}

private function reorderCategorie(?int $parentId, array $children, NestedTreeRepository $repository)
{

  // Has a parent category
  if(null !== $parentId){
    $parent = $repository->find($parentId);
  }
  // It's a root node
  else {
    $parent = null;
  }

  $previousSibling = null;

  foreach ($children as $c){
    // It's a new Categoria
    if(0 == $c['id']){
        $categoria = new Categoria();
    }
    // Retrieves the category from the DB
    else {
        $categoria = $repository->find($c['id']);
    }

    // Init category
    $categoria->setParent($parent);
    $categoria->setNome($c['nome']);
    $categoria->setIcona($c['icona']);

    dump('-------- START CATEGORIA '.$categoria->getNome());

    if(is_null($parent)) {
        dump('Categoria '.$categoria->getNome().' is ROOT');
        $repository->persistAsFirstChild($categoria);
    }
    else{
        dump('Categoria is child of '.$parent->getNome());

        if(is_null($previousSibling)){
            dump('Categoria is the first child of '.$parent->getNome());
            $repository->persistAsFirstChildOf($categoria, $parent);
        } else{
            dump('Categoria is sibling of '.$previousSibling->getNome());
            $repository->persistAsNextSiblingOf($categoria, $previousSibling);
        }
    }

    if(isset($c['children']) && !empty($c['children'])){
        dump('HAS '.count($c['children']).' CHILDREN');
        // Recursive
        $this->reorderCategorie($categoria->getId(), $c['children'], $repository);
    }

    dump('-------- END CATEGORIA '.$categoria->getNome());

    $previousSibling = $categoria;
}

但结果树是

在此处输入图像描述

正如您所看到的,lft 和 rgt 索引是错误的......所以有可能,使用 Gedmo,我想要做什么?如果是的话......我哪里错了?谢谢

4

0 回答 0