How can i display grouped values in Laravel - php

I'm Trying to display restaurant Menus grouped by the categories, for example...
Lunch
Chicken and Chips
Rice
Breakfast
Tea
Coffee
So I have 3 tables in my database, Restaurants, Categories, And Menus
Category Model
class Category extends Model
{
protected $fillable = [
'name'
];
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function menus_type()
{
return $this->hasMany('App\Menu','category_id');
}
}
Menu Model
class Menu extends Model
{
protected $fillable = [
'name',
'price',
'description',
'photoPath',
'restaurant_id',
'category_id',
];
/**
* Menu belongs to Restaurant
*/
public function restaurant()
{
return $this->belongsTo('App\Restaurant');
}
/**
* Menu belongs to category type
*/
public function category_type()
{
return $this->belongsTo('App\Category', 'category_id');
}
}
Restaurants controller
public function show($slug, RestaurantRepository $repository){
if(! $restaurant = $repository->get(['slug' => $slug], with(['cuisines','user', 'photos', 'thumbs', 'region', 'ratings.user']))) return abort('404');
$menus=Menu::with(['category_type'])->where('restaurant_id',$restaurant->id)->get()->groupBy('category_id');
return view('frontend.restaurant.show', compact('restaurant', 'p','menus'));
}
when i Dump this it looks just fine.
Results have been grouped
Now my trouble is on the View when i try to get results of this i get an error.
#if($menus)
<ul>
#foreach($menus as $m)
<li>
{{$m->name}}
</li>
#endforeach
</ul>
#endif
ErrorException (E_ERROR).
Property [name] does not exist on this collection instance.

Iterate inner loop also. 'groupBy()' creates another array with category_id as key.
#if($menus)
<ul>
#foreach($menus as $category_id=>$outer)
#foreach($outer as $k=>$inner)
<li>
{{$category_id}}: {{$inner->name}}
</li>
#endforeach
#endforeach
</ul>
#endif
Updated you query to get from category
$categories = Category::with('menus_type')->get();
return view('frontend.restaurant.show', compact('restaurant', 'p','categories '));
In your view
#if($categories ?? false)
<ul>
#foreach($categories ?? [] as $cat_key=>$category)
<li>
{{$category->name}}
</li>
<li>
<ul>
#foreach($category->menus_type as $menu_key=>$menu)
<li>
{{$menu->name}}
</li>
#endforeach
</ul>
</li>
#endforeach
</ul>
#endif

Related

Laravel subcategories

For an app, I'm creating a scraper.
At the moment I'm at the page where a user can add items to a list with the possibility to create any subcategories where you can add append those items to a specific subcategory.
At the bottom of the page, there is a section where all the subcategories are listed and below each category should be a list where all the items are who are appended to that specific subcategory.
At the moment, I was able to show all the names of the subcategories and all products that are in my main list are stored in the subcategories that has the id. (I hope you can follow what's going on). But I don't know how I can only show the articles who was that specific subcategory in that list instead of all of the main articles..
My code:
My view:
<div class="bg-gray-100 shadow-xl w-11/12 m-auto p-4 rounded-md space-y-6 relative">
<strong>Mijn sublijsten</strong>
#foreach ($subcats as $scat)
<div class="flex lg:flex-row">
<h2>{{ $scat->name }}</h2>
#if ($wishlists->contains('subcat', $cat->id))
#foreach ($wishlists as $item)
<strong>{{$item->article->title}}</strong>
#endforeach
#endif
</div>
#endforeach
</div>
My Controller
public function dashboard($role, $id)
{
$wishlists = Wishlist::all();
$articles = Article::all();
$websites = Website::all();
$categories = Category::all();
$subcats = Subcat::all();
$subcat = Wishlist::find($id)->get();
return view('dashboard', compact('wishlists', 'articles', 'categories', 'websites', 'subcats', 'subcat'));
}
My Model
class Wishlist extends Model
{
protected $table = "wishlists";
protected $fillable = [
'user_id',
'article_id',
'confirmed',
'available',
'score',
'subcat'
];
protected $casts = [
];
public function user()
{
return $this->belongsTo(User::class);
}
public function article()
{
return $this->belongsTo(Article::class);
}
public function subcat()
{
return $this->belongsTo(Subcat::class);
}
}

How can i make three tables relationships in laravel 5.4

I want to create dynamice mega menu but i'm getting error when i'm making tables relationship. Please let me know how can i make relationship.
Table structure Below:-
1) categories
id integer
category varchar
2) subcategories
id integer
subcategory varchar
category_id integer
3) parentcategories
id integer
parentname varchar
subcategory_id integer
Models
Categories.php
protected $table = "categories";
public function sub(){
return $this->hasManyThrough(Subcategories::class,Parentcategories::class,'subcategory_id','category_id');
}
Subcategories.php
protected $table = "subcategories";
public function category()
{
return $this->belongsTo('App\Categories');
}
Parentcategories.php
protected $table = "parentcategories";
public function subcategory()
{
return $this->belongsTo('App\Subcategories');
}
PagesController.php
public function index(){
$categories = Categories::all();
return view('pages.home')->with('categories',$categories);
}
blade template
#foreach($categories as $category)
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
{{ $category->category }} <i class="fa fa-chevron-down"
aria-hidden="true"></i>
</a>
<ul class="mega-menu dropdown-menu">
#foreach($category->sub->take(20) as $subcategory)
<li class="col-sm-3">
<h5>{{$subcategory->subcategory}} <i class="fa fa-caret-right" aria-hidden="true"></i></h5>
<ul class="mega-list">
<li>parent categories comes here</li>
</ul>
</li>
#endforeach
</ul>
</li>
#endforeach
Thanks
As I can see your table are hierarchy is in simillar fashion, I guess this can be done with single table. Create a table named categories and follow the below table structure:
Now create a model Category.php: something like this:
<?php
class Category extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'categories';
public function parent() {
return $this->hasOne('category', 'id', 'parent_id');
}
public function children() {
return $this->hasMany('category', 'parent_id', 'id');
}
public static function tree() {
return static::with(implode('.', array_fill(0, 4, 'children')))->where('parent_id', '=', NULL)->get();
}
}
Now in your controller suppose HomeController.php write:
<?php
class HomeController extends BaseController {
protected $layout = "layouts.main";
public function showWelcome()
{
$items = Category::tree();
$this->layout->content = View::make('layouts.home.index')->withItems($items);
}
}
And in views suppose index.blade.php you can simply pass like this:
<ul>
#foreach($items as $item)
<li>{{ $item->title }}
#foreach($item['children'] as $child)
<li>{{ $child->title }}</li>
#endforeach
</li>
#endforeach
</ul>
This works for n-number for hierarchy, more efficient and a single table categories, hope this helps

Showing Sub-categories on menu only if has products with Laravel

I have simple query which populate menu with Main categories and sub-categories. This work perfectly
// in controller
$cat=Categories::all();
View::share('categories_menu',$cat);
// in view
#foreach($categories_menu as $category_menu)
#if($category_menu->has('subcategories'))
<ul class="nav nav-stacked cat-nav">
<li>
{{ $category_menu['category_name'] }}
#if($category_menu->subcategories->count())
<ul>
#foreach($category_menu->subcategories as $subcategory)
<li class="">{{$subcategory->sub_cat_name}}</li>
#endforeach
</ul>
#endif
</li>
#else
<li><i class="fa fa-link"></i> <span>{{ $category_menu->category_name }}</span></li>
#endif
</ul>
#endforeach
This make output like
Main Category
-Sub Cat
-Sub Cat
Second main category
-Sub in second main category
...
The problem is that it is loading also sub-categories which are empty. I don't want to show them and I tried to change the query with joining all three tables - category, sub_categories, products
This is the query so far
$cat = Categories::select('*', DB::raw('category.category_id AS category_id'))
->leftJoin('products', function($join) {
$join->on('products.category_id', '=', 'category.category_id');
})
->leftJoin('sub_category', function($secondjoin){
$secondjoin->on('sub_category.category_id', '=', 'category.category_id');
})
->whereNotNull('products.sub_cat_id')
->get();
The result is strange ( image )
It's should show me only two main categories each with one sub. On the image you can see my product table
Category 1
-sub1
Category 2
-sub3
If need some more source or something i can provide.
Update with models:
Categories model
class Categories extends Eloquent {
protected $table = 'category';
protected $primaryKey = 'category_id';
public $timestamps = false;
public function products()
{
return $this->hasMany('Product', 'category_id');
}
public function subcategories()
{
return $this->hasMany('SubCategories', 'category_id');
}
}
SubCategories model
class SubCategories extends Eloquent {
protected $table = 'sub_category';
protected $primaryKey = 'sub_cat_id';
public $timestamps = false;
public function category()
{
return $this->belongsTo('Category', 'category_id');
}
public function products()
{
return $this->hasMany('Product', 'sub_cat_id');
}
}
Products model
class Product extends Eloquent {
protected $table = 'products';
protected $primaryKey = 'product_id';
public function categories()
{
return $this->hasMany('Categories', 'category_id');
}
public $timestamps = false;
}
#foreach($categories_menu as $category_menu)
#if($category_menu->has('subcategories'))
<ul class="nav nav-stacked cat-nav">
<li>
{{ $category_menu['category_name'] }}
#if($category_menu->subcategories->count())
<ul>
#foreach($category_menu->subcategories as $subcategory)
#if($subcategory->products->count())
<li class="">{{$subcategory->sub_cat_name}}</li>
#endif
#endforeach
</ul>
#endif
</li>
#else
<li><i class="fa fa-link"></i> <span>{{ $category_menu->category_name }}</span></li>
#endif
</ul>
#endforeach
I added a condition for subcatergy to be displayed only if their products count is above 0.

laravel hasMany relationship not working as expected

I have two models called category and sub-category
Category.php
class Category extends Model
{
protected $table = 'category';
public $timestamps = false;
public function subCategory(){
return $this->hasMany('App\Subcategory', 'category_id');
}
}
Subcategory.php
class Subcategory extends Model
{
protected $table = 'subcategory';
public $timestamps = false;
public function subCategory() {
return $this->belongsTo('App\Category');
}
and I have foreign key column called category_id in my subcategory table in database
this is how I am trying to get all the subcategories for the selected category in my controller
$subcategory = Category::all();
and my blade view
<ul>
#foreach($categories as $categories)
<li class='has-sub'><a href='#'>{{ $categories->category_name }}</a>
<ul>
#foreach($subcategory->subCategory() as $sub)
<li><a href='#'>{{ $sub->subcategory_name }}</a></li>
#endforeach
</ul>
</li>
#endforeach
</ul>
I am able to get all the categories name for now but I can't get the name of sub-categories for the category..What I am missing here?
Your models are fine, i would modify the controller and view to the following:
In your controller
$categories = Category::with('subCategory')->get();
Now in this this case, your categories will be eager loaded with your subcategories. In your example, you make queries in a foreach loop, which is not efficient.
In your view
<ul>
#foreach($categories as $category)
<li class='has-sub'><a href='#'>{{ $category->category_name }}</a>
<ul>
#foreach($category->subCategory as $sub)
<li><a href='#'>{{ $sub->subcategory_name }}</a></li>
#endforeach
</ul>
</li>
#endforeach
</ul>
Notice the variable names, as #aldrin27 mentioned in the comment! ($categories -> $category)
More tweaks
You could use one model for categories and subcategories:
function subCategory() {
return $this->hasMany('App\Category', 'category_id');
}

Menu and child menu in laravel 5.1

So i have in my database a table with id, id_parent, title and so on..
I need to create a list with sublists from that. I need some sort of recursive function but don't know how to do that in laravel..
I tried
class Goals extends Model {
protected $table = 'goals';
public function subgoals() {
return $this->hasMany(SubGoals::class, 'id_category');
}
}
class SubGoals extends Model {
protected $table = 'goals';
public function goals() {
return $this->belongsTo(Goals::class, 'id_category');
}
}
Controller:
$treeView = Goals::with(['SubGoals'])->get();
And view:
#foreach($treeView as $category)
<li>
{{ $category->title }}
<ul>
#foreach($category->subgoals as $subcategory)
<li>{{ $subcategory->title }}</li>
#endforeach
</ul>
</li>
#endforeach
Didn't get the right result..
Maybe someone have a snippet..
You dont need to create 2 classes, just need one like your example Goal.
class Goal extends Model {
protected $table = 'goals';
public function subgoals() {
return $this->hasMany(Goal::class, 'parent_id', 'id');
}
}
then in the controller you need to "Query all parent Goals" like this:
$parent_goals = Goal::whereNull('parent_id')->get();
and finally in the view:
#foreach($parent_goals as $goal)
<li>
{{ $goal->title }}
<ul>
#foreach($goal->subgoals as $subgoal)
<li>{{ $subgoal->title }}</li>
#endforeach
</ul>
</li>
#endforeach
that's it. hope that help's you.

Categories