Php Laravel菜单自递归
模型Php Laravel菜单自递归,php,laravel,laravel-4,Php,Laravel,Laravel 4,模型 class Menu extends Eloquent { public static $table = 'menus'; public function parent_menu() { return $this->belongs_to('Menu', 'parent_id'); } } 如何将其放入控制器: $menus = Menu::with('parent_menu')-
class Menu extends Eloquent {
public static $table = 'menus';
public function parent_menu()
{
return $this->belongs_to('Menu', 'parent_id');
}
}
如何将其放入控制器:
$menus = Menu::with('parent_menu')->get();
如何在视图中渲染它:
foreach($menus as $m)
{
echo $m->parent_menu->title;
}
看起来当关系在表中时出现问题,我得到一个错误
`trying to get property of non object`
有解决办法吗?这可能会有所帮助。下面是我如何处理产品类别/子类别的 型号:
<?php
class Category extends Eloquent {
protected $table = 'product_category';
public function subcat()
{
return $this->hasMany('Category', 'node_id')->orderBy('position');
}
我已经实现了一种在Laravel 4的菜单中获得无限深度的方法。这并不完全是你所要求的,但是这种技术应该很容易适应 首先,我的菜单只是一个数组(目前),它被分配给主视图,看起来像这样
$menu = array(
array(
'name' => 'item1',
'url' => '/'
),
array(
'name' => 'item2',
'url' => '/',
'items' => array(
array(
'name' => 'subitem1',
'url' => '/'
),
array(
'name' => 'subitem2',
'url' => '/'
)
)
)
);
您也可以通过使用模型轻松实现此结构。您将需要函数子项
或其他功能,因为我们将从上到下而不是从下到上呈现菜单
现在,在我的主刀片模板中,我执行以下操作:
<ul>
@foreach ($menu as $item)
@include('layouts._menuItem', array('item' => $mainNavItem))
@endforeach
</ul>
正如您所见,此模板递归地调用自身,但使用不同的$item
变量。这意味着你可以在你的菜单结构中选择你想要的深度。(php块只是用来准备一些变量,这样我就可以保持实际的模板代码干净易读,从技术上讲,这不是必需的)
我剥离了上面代码片段中的Twitter引导代码以保持简单(我的模板/数组中实际上有标题、下拉开关、图标、分隔符等等),因此代码没有经过测试。完整版本对我来说很好,所以如果我在某个地方犯了错误,请告诉我
希望这对你(或其他人)有所帮助,因为这是一个相当古老的问题。如果您需要更多的提示/帮助,或者需要我的完整代码,请告诉我
快乐编码 我相信以下是在laravel中进行递归的正确方法 假设我们有一个子关系,您可以将其添加到模型类中:
public function getDescendants ( $parent= false ) {
$parent = $parent ?: $this;
$children = $parent->children()->get();
foreach ( $children as $child ) {
$child->setRelation(
'children',
getDescendants( $child )
);
}
return $children;
}
上面将递归地获取所有子记录,您可以这样访问它们:
$d = Category::find(1)->getDescendants();
foreach ( $d as $child_level_1 ) {
foreach ( $child_level_1->children as $child_level_2 ) {
foreach ( $child_level_2->children as $child_level_3 ) {
// ...... this can go on for infinite levels
}
}
}
尽管未经测试,但以下内容可能有助于将所有递归关系展平为一个模型集合():
这样,您可以执行以下操作:
// This will get the descenands and flatten them recursively
$d = Category::find(1)->getDescendants()->flattenRelation( 'children' );
// This will give you a flat collection of all the descendants
foreach ( $d as $model ) {
}
具有无限子菜单的My laravel菜单(数据库中的菜单项) 之后,我将菜单html放入macro.php
HTML::macro('MakeNavigation', function($data) {
foreach ($data as $key => $value) {
if($value->submenu) {
echo '<li class="'.$value->activeClass.'">
<a href="'.$value->link.'" class="'.$value->activeClass.'">"'
.$value->name.' <span class="fa arrow"></span>
</a>';
echo "<ul class='nav nav-".$value->level."-level ".$value->inClass." '>";
HTML::MakeNavigation($value->submenu);
echo "</ul>";
}
else {
echo '<li class="'.$value->activeClass.'">
<a href="'.$value->link.'" class="'.$value->activeClass.'">'
.$value->name.'
</a>';
}
echo "</li>";
}});
看起来我需要在这种情况下使用透视表。您确定要获取的菜单项具有父菜单项吗?“尝试获取非对象的属性”表明没有可用的
parent_菜单
。在这里为来自搜索的人发布此消息,但这对于级别是有限的,我想在深层次上使其不受限制
// Add this to your model
public function newCollection ( array $models = array() ) {
return new CustomCollection( $models );
}
// Create a new file that extends the orginal collection
// and add the flattenRelation method
class CustomCollection extends Illuminate\Database\Eloquent\Collection {
// Flatten recursive model relations
public static function flattenRelation ( $relation ) {
$collection = $this;
// Loop through the collection models
foreach ( $collection as $model ) {
// If the relation exists
if ( isset($model->relations[$relation]) ) {
// Get it
$sub_collection = $model->relations[$relation];
// And merge it's items with the original collection
$collection = $collection->merge(
$sub_collection->flatten($relation)
);
// Them remove it from the relations
unset( $model->relations[$relation] );
}
}
// Return the flattened collection
return $collection;
}
}
// This will get the descenands and flatten them recursively
$d = Category::find(1)->getDescendants()->flattenRelation( 'children' );
// This will give you a flat collection of all the descendants
foreach ( $d as $model ) {
}
public function CreateMenu( $parid, $menu, $level ) {
$output = array();
$action= Route::current()->getUri();
$uri_segments = explode('/', $action);
$count=count($uri_segments);
foreach( $menu as $item => $data ) {
if ($data->parent_id == $parid) {
$uri='';
$output[ $data->id ] = $data;
for($i=0; $i<=$level; $i++) {
if($i < $count) {
$uri.="/".Request::segment($i+1);
}
if($uri == $data->link ) {
$output[ $data->id ]->activeClass = 'active';
$output[ $data->id ]->inClass = 'in';
}
else {
$output[ $data->id ]->activeClass = '';
$output[ $data->id ]->inClass = '';
}
$output[ $data->id ]->level = $level+2;
}
$output[ $data->id ]->submenu = self::CreateMenu( $data->id, $menu, $level+1 );
}
}
return $output;
}
$navitems=DB::table('navigations')->get();
$menu=BaseController::CreateMenu(0,$navitems,0);
return View::share($menu);
HTML::macro('MakeNavigation', function($data) {
foreach ($data as $key => $value) {
if($value->submenu) {
echo '<li class="'.$value->activeClass.'">
<a href="'.$value->link.'" class="'.$value->activeClass.'">"'
.$value->name.' <span class="fa arrow"></span>
</a>';
echo "<ul class='nav nav-".$value->level."-level ".$value->inClass." '>";
HTML::MakeNavigation($value->submenu);
echo "</ul>";
}
else {
echo '<li class="'.$value->activeClass.'">
<a href="'.$value->link.'" class="'.$value->activeClass.'">'
.$value->name.'
</a>';
}
echo "</li>";
}});
{{ HTML::MakeNavigation($menu) }}