Php 拉雷维尔4-雄辩。无限多个子元素进入可用数组?

Php 拉雷维尔4-雄辩。无限多个子元素进入可用数组?,php,parent-child,laravel,laravel-4,eloquent,Php,Parent Child,Laravel,Laravel 4,Eloquent,我有一张分类表。每个类别都可以有一个可选的父级(如果没有父级,则默认为0) 我想做的是构建一个简单的html列表树,其中包含类别的级别 示例日期: Foods -- Fruit ---- Apple ---- Banana ---- Orange -- Veg ---- Cucumber ---- Lettuce Drinks -- Alcoholic ---- Beer ---- Vodka Misc -- Household Objects ---- Kitchen ------ Elect

我有一张分类表。每个类别都可以有一个可选的父级(如果没有父级,则默认为0)

我想做的是构建一个简单的html列表树,其中包含类别的级别

示例日期:

Foods
-- Fruit
---- Apple
---- Banana
---- Orange
-- Veg
---- Cucumber
---- Lettuce
Drinks
-- Alcoholic
---- Beer
---- Vodka
Misc
-- Household Objects
---- Kitchen
------ Electrical
-------- Cooking
---------- Stove
---------- Toaster
---------- Microwave
请注意,这需要在大约10个“级别”下工作。我希望它是无限的,但我真的不想走上使用嵌套集模型的道路,因为它会导致这个项目的巨大延迟

laravel在这方面的文档非常糟糕,没有真正的参考,甚至没有从哪里开始。我已经玩了好几天了,想知道该怎么做,但是如果没有一个巨大的for-each循环块的话,我似乎什么也做不到

在我的模型中,我使用了以下数据树:

<?php
class Item extends Eloquent {
    public function parent()
    {
        return $this->hasOne('Item', 'id', 'parent_id');
    }

    public function children()
    {
        return $this->hasMany('Item', 'parent_id', 'id');
    }

    public function tree()
    {
        return static::with(implode('.', array_fill(0,10, 'children')))->where('parent_id', '=', '0')->get();
    }
}

这比我平常早上玩的纵横填字游戏有趣多了

这里有一个ItemsHelper类,它将完成您正在寻找的任务,更好的是,它将尽可能地递归

app/models/ItemsHelper.php:

<?php

  class ItemsHelper {

    private $items;

    public function __construct($items) {
      $this->items = $items;
    }

    public function htmlList() {
      return $this->htmlFromArray($this->itemArray());
    }

    private function itemArray() {
      $result = array();
      foreach($this->items as $item) {
        if ($item->parent_id == 0) {
          $result[$item->name] = $this->itemWithChildren($item);
        }
      }
      return $result;
    }

    private function childrenOf($item) {
      $result = array();
      foreach($this->items as $i) {
        if ($i->parent_id == $item->id) {
          $result[] = $i;
        }
      }
      return $result;
    }

    private function itemWithChildren($item) {
      $result = array();
      $children = $this->childrenOf($item);
      foreach ($children as $child) {
        $result[$child->name] = $this->itemWithChildren($child);
      }
      return $result;
    }

    private function htmlFromArray($array) {
      $html = '';
      foreach($array as $k=>$v) {
        $html .= "<ul>";
        $html .= "<li>".$k."</li>";
        if(count($v) > 0) {
          $html .= $this->htmlFromArray($v);
        }
        $html .= "</ul>";
      }
      return $html;
    }
  }
虽然我的视图不使用items变量,但我将它传递到这里,因为您可能还想用它们做其他事情

最后,我的
app/views/hello.php
只有一行:

输出如下所示:

  • 厨房
  • 电气
    • 烹饪
        炉子
        • 烤面包机
            • 微波
                                  微波炉


                                注意:您的SQL小提琴有5(“橙色”)作为黄瓜和莴苣的父id,我必须将其更改为6(“蔬菜”)。

                                我使用此函数使其工作

                                 //Returns Root elements
                                 public function scopeRoot($query) {
                                        $all = $query->whereParent(0)->get();
                                        $collection = $all->filter(function($single) {
                                            if ($single->ModelFilter('GET')) {
                                                return $single;
                                            }
                                        });
                                        return $collection;
                                    }
                                    //Recursive call
                                    public function traverse() {
                                        self::_traverse($this->Children, $array, $this);
                                        return $array;
                                    }
                                
                                    //This function build a multidimensional array based on a collection of elements
                                    private static function _traverse($collection, &$array, $object) {
                                        $new_array = array();
                                        foreach ($collection as $element) {
                                            self::_traverse($element->Children, $new_array, $element);
                                        }
                                        $array[] = $object;
                                        if (count($new_array) > 0) {
                                            $array[] = $new_array;
                                        }
                                    }
                                
                                首先,我得到一个根元素的集合,这些是我传递给视图的元素,我想在其中列出树

                                那我真的

                                 <ul class="bg-info cat-list">
                                        @foreach($categories as $category)
                                        <?php
                                        $array = $category->traverse();
                                        list_view($array);
                                        ?>
                                        @endforeach
                                    </ul>
                                
                                  @foreach($categories作为$category) @endforeach
                                使用此函数

                                //Prints a multidimensional array as a nested HTML list
                                function list_view($element, $ul = true) {
                                    foreach ($element as $value) {
                                        if (!is_array($value)) {
                                            echo "<li>";
                                            echo $value->name;
                                        } else {
                                            echo ($ul) ? "<ul>" : "<ol>";
                                            list_view($valuce, $ul);
                                            echo "</li>";
                                            echo ($ul) ? "</ul>" : "</ol>";
                                        }
                                    }
                                }
                                
                                //将多维数组打印为嵌套的HTML列表
                                函数列表\视图($element,$ul=true){
                                foreach($value形式的元素){
                                如果(!是_数组($value)){
                                回声“
                              • ”; echo$value->name; }否则{ 回声($ul)?“
                                  ”:”; 列表视图($valuce,$ul); 回声“”; 回声($ul)?“
                                ”:”; } } }

                              • 希望它有帮助

                                我已经扩展了Mark Smith接受的答案,允许生成的列表引用传递到类中的添加数据

                                这个类的工作方式基本相同,但我已经打包好了,希望它可以很容易地使用

                                只需在控制器中引用helper类:

                                use App\Helpers\CategoryHierarchy;
                                
                                然后,您可以手动实例化该类,或者使用Laravel 5的方法注入,这样会更好:

                                $products = $product->getAllProducts();
                                $hierarchy->setupItems($products);
                                return $hierarchy->render();
                                
                                这可以输出以下内容:

                                <ul class='simple-list'>
                                   <li><input type="checkbox" name="hierarchy-checkboxes[]" value="1" >Home delivery</li>
                                      <ul>
                                        <li><input type="checkbox" name="hierarchy-checkboxes[]" value="2" >Italian</li>
                                          <ul>
                                            <li><input type="checkbox" name="hierarchy-checkboxes[]" value="3" >Pizza</li>
                                            <li><input type="checkbox" name="hierarchy-checkboxes[]" value="4" >Pasta</li>
                                          </ul>
                                        <li><input type="checkbox" name="hierarchy-checkboxes[]" value="5" >Burgers</li>
                                      </ul>
                                </ul>
                                
                                • 送货上门
                                  • 意大利人
                                    • 披萨
                                    • 面食
                                  • 汉堡

                                回购协议是可用的:这更详细地解释了这一点。

                                嵌套集实际上更简单。另外,已经有一些现有的包,比如or.Jason,与公认的答案相比,嵌套集有什么优势?我必须在两者之间做出决定。对于Baum来说,似乎无论如何都没有办法检索到那棵树,除非你也使用被接受的答案。@MarkSmith-很好的答案,谢谢!只是在努力理解如何向数组添加附加值?或者甚至添加命名值?例如:
                                {id:'2',name:'Parent 2',children:[{id:'5',name:'Sub 2a'},{id:'6',name:'Sub 2b'}]}
                                非常有用!谢谢我还想知道如何添加附加值@Marksmith这是一个好的解决方案,但只有一件事是不好的。问题是视图是在模型中生成的,而不是视图本身,如果您遵循MVC模式,那么除了视图文件之外,您不应该在任何地方都有任何HTML。还有另一种解决方案,使用刀片子模板的递归调用,但仍然不是一个好的解决方案,尽管它遵循MVC模式!是否有方法返回正在迭代的整个对象?而不仅仅是名字?
                                <ul class='simple-list'>
                                   <li><input type="checkbox" name="hierarchy-checkboxes[]" value="1" >Home delivery</li>
                                      <ul>
                                        <li><input type="checkbox" name="hierarchy-checkboxes[]" value="2" >Italian</li>
                                          <ul>
                                            <li><input type="checkbox" name="hierarchy-checkboxes[]" value="3" >Pizza</li>
                                            <li><input type="checkbox" name="hierarchy-checkboxes[]" value="4" >Pasta</li>
                                          </ul>
                                        <li><input type="checkbox" name="hierarchy-checkboxes[]" value="5" >Burgers</li>
                                      </ul>
                                </ul>