Laravel returning children of parents in same table

本小妞迷上赌 提交于 2019-11-29 02:56:42

问题


Using Laravel 5.1, I am trying to create a menu list from a MySQL categories table. My service provider returns data, but I don't understand how to create the child categories in a foreach loop. When I perform the loop, only the last row of the child query is returned. Any guidance would be appreciated.

categories Table

id  | cat_name      | cat_parent_id
--- | --------------| ------------- 
1   | Parent Cat 1  | NULL 
2   | Parent Cat 2  | NULL 
3   | Child Cat 1   | 2 
4   | Child Cat 2   | 2 
5   | Parent Cat 3  | NULL 
6   | Child Cat 3   | 5

Desired Result

Parent Cat 1
Parent Cat 2
    Child Cat 1
    Child Cat 2
Parent Cat 3
    Child Cat 3

viewComposerServiceProvider.php

public function boot()
{
       $this->composeTopCategoryNavigation();
       $this->composeSubCategoryNavigation();
}

private function composeTopCategoryNavigation()
{
    view()->composer('partials.header', function($view)
        {
            $view->with('top_cats', Category::whereNull('cat_parent_id')->orderBy('cat_name', 'asc')->get());
        });
}

private function composeSubCategoryNavigation()
{
        view()->composer('partials.header', function($view)
        {
            $view->with('sub_cats', Category::whereNotNull('cat_parent_id')->orderBy('cat_name', 'asc')->get());
        });
}

header view

<ul>
@foreach ($top_cats as $top_cat)
  <?php $top_cat_slug = str_slug( $top_cat->cat_name, "-"); ?>
  <li>{{ $top_cat->cat_name }}
    @foreach ($sub_cats as $sub_cat)
            @if ( $sub_cat->cat_parent_id === $top_cat->id )
                <ul>
                  <li{{ $sub_cat->cat_name }}</li>
                </ul>
                @endif
        @endforeach
   </li>
@endforeach
</ul>

回答1:


First of all, what you are doing is inefficient. Your view iterates through all subcategories for every parent category. If you defined relations properly and made use of Eloquent's eager loading, you could fetch and access child categories in easier way.

Start with defining relations:

class Category extends Model {
  //each category might have one parent
  public function parent() {
    return $this->belongsToOne(static::class, 'cat_parent_id');
  }

  //each category might have multiple children
  public function children() {
    return $this->hasMany(static::class, 'cat_parent_id')->orderBy('cat_name', 'asc');
  }
}

Once you have the relations defined properly, you can fetch whole category tree like below:

view()->composer('partials.header', function($view) {
  $view->with('categories', Category::with('children')->whereNull('cat_parent_id')->orderBy('cat_name', 'asc')->get());
});

The second composer won't be needed, as parent categories already contain children.

Now, you only need to display the categories in your view:

<ul>
  @foreach ($categories as $parent)
    <li>{{ $parent->cat_name }}
      @if ($parent->children->count())
        <ul>
          @foreach ($parent->children as $child)
            <li>{{ $child->cat_name }}</li>
          @endforeach
        </ul>
      @endif
    </li>
  @endforeach
</ul>



回答2:


I've found the solution myself. I have to iterate through the results to get access to the member variable.

@foreach($locations as $location)
            <tr>
                <td>
                    {{$location->location_id}}
                </td>
                <td>
                    @foreach($location->members as $member)
                        {{$member->first_name}}
                    @endforeach
                </td>
                <td>

                </td>
            </tr>
        @endforeach


来源:https://stackoverflow.com/questions/32122849/laravel-returning-children-of-parents-in-same-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!