symfony - 类别树

时间:2018-03-24 14:59:12

标签: php symfony

我需要为FancyTree(JSON格式)构建类别树,所以我这样做:
类别实体

class Category
{    
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="children")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
     */
    private $parent;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Category", mappedBy="parent")
     */
    private $children;

    // ...

    public function __construct()
    {
        $this->children = new ArrayCollection();
    }

    // ...

    /**
     * @return Category
     */
    public function getParent(): Category
    {
        return $this->parent;
    }

    /**
     * @return Collection|Category[]
     */
    public function getChildren()
    {
        return $this->children;
    }
}

和构建树的方法:

public function buildCategoryTree($categories, ?int $activeCategory = null)
{
    $tree = [];
    foreach ($categories as $category) {
        $tmp = [
            "title" => $category->getName(),
            "expanded" => true,
            "folder" => true
        ];

        if ($category->getId() === $activeCategory)
            $tmp['active'] = true;

        if ($category->getChildren() != null)
            $tmp['children'] = $this->buildCategoryTree($category->getChildren(), $activeCategory);

        $tree[] = $tmp;
    }

    return $tree;
}

但是我得到无限循环 - 为什么? 我得到了所有指定类别的孩子的正确答案(我不会手动添加它),我可以毫无问题地进行迭代。

4 个答案:

答案 0 :(得分:0)

你可以试试这个:

 function buildTree($categories, $parentCategory = null) {
        $branch = array();

        foreach ($categories as $element) {
            if ($element->getParent() == $parentCategory) {
                $children = buildTree($categories, $element);
                if ($children) {
                    $element->getChildren() = $children;
                }
                $branch[$element->getId()] = $element;
                unset($categories[$element->getId()]);
            }
        }
        return $branch;
    }

请检查一下:

<?php

use Doctrine\Common\Collections\ArrayCollection;

/** @ORM\Entity */
class Category {

    /**
     * @ORM\Id
     * @ORM\Column(type="integer", name="id")
     * @ORM\GeneratedValue
     */
    protected $id;

    // ...

    /**
     * @ORM\OneToMany(targetEntity="Category", mappedBy="parent")
     */
    protected $children;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="children")
     * @ORM\JoinColumn(name="parent", referencedColumnName="id")
     */
    protected $parent;

    public function __construct() {
        $this->children = new ArrayCollection();
    }

    // Once you have that, accessing the parent and children should be straight forward 
    // (they will be lazy-loaded in this example as soon as you try to access them). IE:

    public function getParent() {
        return $this->parent;
    }

    public function getChildren() {
        return $this->children;
    }

    // ...

    // always use this to setup a new parent/child relationship
    public function addChild(Category $child) {
       $this->children[] = $child;
       $child->setParent($this);
    }

    public function setParent(Category $parent) {
       $this->parent = $parent;
    }

}

答案 1 :(得分:0)

假设您正在尝试实现某种类型的层次结构,如下所示:

array (size=1)
  6 => 
    array (size=4)
      'title' => string 'title6'
      'expanded' => boolean true
      'folder' => boolean true
      'children' => 
        array (size=2)
          4 => 
            array (size=3)
              'title' => string 'title4'
              'expanded' => boolean true
              'folder' => boolean true
          3 => 
            array (size=4)
              'title' => string 'title3'
              'expanded' => boolean true
              'folder' => boolean true
              'children' => 
                array (size=1)
                  2 => 
                    array (size=3)
                      'title' => string 'title2'
                      'expanded' => boolean true
                      'folder' => boolean true

尝试这样的事情:

public function buildTree($rootCategory, &$tree, $activeCategory = null) {
        $tree = ["title" => $rootCategory->getName(),
            "expanded" => true,
            "folder" => true
        ];

        if ($rootCategory->getId() === $activeCategory)
            $tree['active'] = true;

        if (count($rootCategory->getChildren()->toArray())) {
            foreach ($rootCategory->getChildren() as $child) {
                $this->buildTree($child, $tree['children'][$child->getId()], $activeCategory);
            }
        }
    }

你第一次这样称呼它:

buildTree($rootCategory, $tree[$rootCategory->getId()], $activeCategoryId);

其中$rootCategory是没有的那个,而$tree是一个空数组。

基本上,您创建一个void函数并仅传递构建树的根类别,同时将每个节点添加到$tree,其中包含整个结构算法完成后

让我知道它是怎么回事。

答案 2 :(得分:0)

private function categoryTree($parent_id = null)
{
    $a=array();
    $rows = $this->findBy(array('parent' => $parent_id), array('id' => 'ASC'));

    foreach ($rows as $row) {
        array_push(
            $a,
            array_filter([
                $row->getId() => $row->getName(),
                'children' => $this->categoryTree($row->getId())
            ])
        );
    }
    return $a;
}

答案 3 :(得分:0)

有“教义扩展”项目。它具有 Tree 嵌套行为,可用于解决问题。

URL:https://github.com/Atlantic18/DoctrineExtensions/blob/HEAD//doc/tree.md

Symfony捆绑包:https://symfony.com/doc/master/bundles/StofDoctrineExtensionsBundle/index.html