duandu6497 2018-02-14 15:44
浏览 34
已采纳

构建类别树Symfony3

I'm trying to build a category tree in Symfony3.

I have the following:

Category Entity:

<?php    
namespace AppBundle\Entity;


use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\CategoryRepository")
 * @ORM\Table(name="category")
 */
class Category
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="children")
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     */
    private $id;
    /**
     * @ORM\Column(type="string")
     */
    private $name;
    /**
     * @ORM\Column(type="string", unique=true)
     */
    private $slug;
    /**
     * One Category has Many Categories.
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Category", mappedBy="parent")
     */
    private $children;
    /**
     * Many Categories have One Category.
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="children")
     */
    private $parent;
    /**
     * @ORM\Column(type="string")
     */
    private $pageTitle;
    /**
     * @ORM\Column(type="text")
     */
    private $description;
    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\User")
     * @ORM\JoinColumn(name="created_by", referencedColumnName="id")
     */
    private $created_by;

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return mixed
     */
    public function getSlug()
    {
        return $this->slug;
    }

    /**
     * @param mixed $slug
     */
    public function setSlug($slug)
    {
        $this->slug = $slug;
    }

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

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

    /**
     * @return mixed
     */
    public function getPageTitle()
    {
        return $this->pageTitle;
    }

    /**
     * @param mixed $pageTitle
     */
    public function setPageTitle($pageTitle)
    {
        $this->pageTitle = $pageTitle;
    }

    /**
     * @return mixed
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @param mixed $description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * @return mixed
     */
    public function getChildren()
    {
        return $this->children;
    }

    /**
     * @param mixed $children
     */
    public function setChildren($children)
    {
        $this->children = $children;
    }

    /**
     * @return mixed
     */
    public function getCreatedBy()
    {
        return $this->created_by;
    }

    /**
     * @param mixed $created_by
     */
    public function setCreatedBy($created_by)
    {
        $this->created_by = $created_by;
    }

    public function __toString()
    {
        return (string) $this->getName();
    }
}

CategoryRepository:

<?php    
namespace AppBundle\Repository;


use Doctrine\ORM\EntityRepository;

class CategoryRepository extends EntityRepository
{
    public function findAllParentCategories()
    {
        return $this->createQueryBuilder('category')
            ->where('category.parent IS NULL')
            ->getQuery()
            ->execute();
    }
}

Code to build the tree:

/**
 * @Route("/category")
 */
public function createCategoryMenu()
{
    $categoryRepository = $this->getDoctrine()->getRepository('AppBundle:Category');
    $categories = $categoryRepository->findAllParentCategories();

    $test = $this->generateCategoryMenu($categories, '');
    echo $test;
    exit;
}

protected function generateCategoryMenu($categories, $tree) {
    $tree .= "<ul>";
    foreach($categories as $category) {
        $tree .= "<li>" . $category->getName();
        if($category->getChildren() != null) {
            $tree .= $this->generateCategoryMenu($category->getChildren(), $tree);
        }
        $tree .= "</li>";
    }
    $tree .= "</ul>";

    return $tree;
}

In my head, this should work, and I cannot figure out why it is not working. I get the following result:

<ul><li>Hiking<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Men<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Men<ul></ul></li></ul></li></ul></li><li>Survival<ul><li>Hiking<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Men<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Men<ul></ul></li></ul></li></ul></li><li>Survival<ul><li>Axes<ul><li>Hiking<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Men<ul><li>Hiking<ul><li>Backpacks<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Men<ul></ul></li></ul></li></ul></li><li>Survival<ul><li>Axes<ul></ul></li></ul></li></ul>

I'm expecting the following result:

<ul><li>Hiking<ul><li>Backpacks<ul></ul></li><li>Shoes<ul><li>Men<ul></ul></li></ul></li></ul></li><li>Survival<ul><li>Axes<ul></ul></li></ul></li></ul>

As you can see, my desired <ul> is the end of the larger <ul>. Why is it rendering all those duplicate <li>-tags?

</div>
  • 写回答

1条回答 默认 最新

  • dovhpmnm31216 2018-02-15 08:55
    关注

    The problem (and solution) is quite simple. In the recursive call, you pass in the already partly built tree:

    $tree .= $this->generateCategoryMenu($category->getChildren(), $tree);
    // ^--------------------------------------------------------------^
    

    And then concatenate the result to the tree in the calling function. Effectively duplicating the entire tree at this point.

    The solution: Simply don't pass down the tree. Which then makes passing in the tree also unnecessary. E.g.:

    protected function generateCategoryMenu($categories) {
        $tree = "<ul>"; // initialize fresh
        foreach($categories as $category) {
            $tree .= "<li>" . $category->getName();
            if($category->getChildren() != null) {
                // just add the result
                $tree .= $this->generateCategoryMenu($category->getChildren());
            }
            $tree .= "</li>";
        }
        $tree .= "</ul>";
    
        return $tree;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改