我在 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,我想要做什么?如果是的话......我哪里错了?谢谢