Laravel 4 - 雄辩。无限的孩子变成可用的数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16541528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel 4 - Eloquent. Infinite children into usable array?
提问by Sk446
I've got a categories table. Each category can have an optional parent (Defaults to 0 if no parent).
我有一个类别表。每个类别都可以有一个可选的父级(如果没有父级,则默认为 0)。
What I want to do is build a simple html list tree with the levels of the categories.
我想要做的是用类别的级别构建一个简单的 html 列表树。
Example date:
示例日期:
Foods
-- Fruit
---- Apple
---- Banana
---- Orange
-- Veg
---- Cucumber
---- Lettuce
Drinks
-- Alcoholic
---- Beer
---- Vodka
Misc
-- Household Objects
---- Kitchen
------ Electrical
-------- Cooking
---------- Stove
---------- Toaster
---------- Microwave
Note that this needs to work for around 10 'levels'. I'd love it to be infinite but I really dont want to be going down the route of using a nested set model as it'll cause huge delays on this project.
请注意,这需要为大约 10 个“级别”工作。我希望它是无限的,但我真的不想沿着使用嵌套集模型的路线走下去,因为它会导致这个项目的巨大延迟。
The docs on this for laravel are terrible, with no real reference as to where to even start. I've been playing with it for days trying to work out what to do and seem to be getting nowhere without a huge messy block of for each loops within each other 10 times.
关于 laravel 的文档很糟糕,甚至没有真正提到从哪里开始。我已经玩了好几天了,试图弄清楚要做什么,但如果没有一个巨大的、混乱的 for 每个循环块 10 次,我似乎一无所获。
I've got my tree of data using the following in my model:
我在我的模型中使用以下内容获得了我的数据树:
<?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();
}
}
This gets all the parent and children up to a level of 10. This works fine, but you cant really then do anything with the child data without manually having 10 foreach loops within each other.
这使所有父级和子级达到 10 级。这很好用,但是如果没有手动在彼此内部有 10 个 foreach 循环,您就无法真正对子数据执行任何操作。
What am I doing wrong here? Surely this shouldn't be this hard/poorly executed? All I want do do is get a simple html list with the items in a tree structure.
我在这里做错了什么?当然,这不应该如此艰难/执行不力吗?我想要做的就是获取一个简单的 html 列表,其中包含树结构中的项目。
I've put together a quick SQLFiddle example of the dummy data used above: http://sqlfiddle.com/#!2/e6d18/1
我已经整理了一个上面使用的虚拟数据的快速 SQLFiddle 示例:http://sqlfiddle.com/#!2/e6d18/1
回答by Mark Smith
This was much more fun than my usual morning crossword puzzle. :)
这比我平时早上的填字游戏有趣多了。:)
Here is an ItemsHelper class that will do what you are looking for, and better yet will recurse as far down as you want.
这是一个 ItemsHelper 类,它将执行您正在寻找的操作,并且更好地递归到您想要的范围。
app/models/ItemsHelper.php:
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;
}
}
I just used a new installation of Laravel 4 and the basic hello.php
view.
我刚刚使用了新安装的 Laravel 4 和基本hello.php
视图。
Here is my route in app/routes.php
:
这是我的路线app/routes.php
:
Route::get('/', function()
{
$items = Item::all();
$itemsHelper = new ItemsHelper($items);
return View::make('hello',compact('items','itemsHelper'));
});
Although my view doesn't use the items variable, I'm passing it here because you probably will want to do something else with them too.
尽管我的视图不使用 items 变量,但我将它传递到这里是因为您可能也想用它们做其他事情。
And finally, my app/views/hello.php
just has one line:
最后,我app/views/hello.php
只有一行:
<?= $itemsHelper->htmlList(); ?>
<?= $itemsHelper->htmlList(); ?>
The output looks like this:
输出如下所示:
- Foods
- Fruit
- Apple
- Banana
- Orange
- Veg
- Cucumber
- Lettuce
- 食品
- 水果
- 苹果
- 香蕉
- 橘子
- 蔬菜
- 黄瓜
- 生菜
- Drinks
- Alcoholic
- Beer
- Vodka
- 饮料
- 酒鬼
- 啤酒
- 伏特加酒
- Misc
- Household Objects
- Kitchen
- Electrical
- Cooking
- Stove
- Toaster
- Microwave
- 杂项
- 家居用品
- 厨房
- 电气
- 烹饪
- 火炉
- 烤面包机
- 微波
Note:your SQL Fiddle had 5 ("Orange") as the parent_id for Cucumber and Lettuce, I had to change it to 6 ("Veg").
注意:您的 SQL Fiddle 有 5(“Orange”)作为 Cucumber 和 Lettuce 的 parent_id,我不得不将其更改为 6(“Veg”)。
回答by Amo
I've expanded on the accepted answer by Mark Smith to allow generated lists to reference addition data that is passed into the class.
我已经扩展了 Mark Smith 接受的答案,以允许生成的列表引用传递到类中的添加数据。
The class works in pretty much the same way, but I've packaged it up so hopefully it can be used easily.
该类的工作方式几乎相同,但我已将其打包,因此希望它可以轻松使用。
Just reference the helper class in your controller:
只需在您的控制器中引用 helper 类:
use App\Helpers\CategoryHierarchy;
You can then either instantiate the class manually, or using Laravel 5's method injection things get even better:
然后你可以手动实例化这个类,或者使用 Laravel 5 的方法注入,事情会变得更好:
$products = $product->getAllProducts();
$hierarchy->setupItems($products);
return $hierarchy->render();
This can output the following:
这可以输出以下内容:
<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>
A repo is available: https://github.com/amochohan/CategoryHierarchywhich explains in some more detail.
一个 repo 是可用的:https: //github.com/amochohan/CategoryHierarchy,它更详细地解释了。
回答by Carlos Arturo Alaniz
I use this functions to make it work.
我使用这个函数来使它工作。
//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;
}
}
First I get a collection of the root elements those are the ones that I pass to my views where I want to list the tree...
首先,我得到一个根元素的集合,这些根元素是我传递给我想要列出树的视图的那些......
Then I do ...
那我做...
<ul class="bg-info cat-list">
@foreach($categories as $category)
<?php
$array = $category->traverse();
list_view($array);
?>
@endforeach
</ul>
Using this function...
使用这个功能...
//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>";
}
}
}
Hope it helps
希望能帮助到你