Don't show empty parent category in Laravel - php

I have parent and child categories on the page. What I'm trying to do is when there is no products and no sub-categories assigned in some parent category to not be shown on the page.
So I have this in Category model
public function item()
{
return $this->hasMany('Item','category_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id');
}
public function getCategories()
{
$categoires = Category::where('parent_id',0)->get();
$categoires = $this->addRelation($categoires);
return $categoires;
}
public function selectChild( $id )
{
$categoires = Category::where('parent_id',$id)->where('published', 1)->get();
$categoires = $this->addRelation($categoires);
return $categoires;
}
This in the controller
public function index()
{
$Category = new Category;
$allCategories = $Category->getCategories();
return view('frontend.home', compact('allCategories', 'unviewedMessagesCount'));
}
And this on the blade view
#foreach($allCategories as $category)
{!!$category->title!!} ({!! $category->itemCount!!})
<p class="card-text">
#foreach($category->subCategory as $subcategory)
{!!$subcategory->title!!} {!! $subcategory->itemCount !!}
#endforeach
</p>
View Category
#endforeach
This is sample of the records in category table there are column
id | title | parent
1 Main cat 0
2 Sub-Cat 1
3 Sub-Cat 2 1
4 Main cat 2 0
So each parent is 0 and each child(sub category) has the parent ID
item table has also reference to category table -> column category_id
I can't figured it out how to make the condition if no items and no childs to not show it on page.

In Controller
$allCategories = Category::where('parent_id', 0)->has('children.item')
->with(['children'=> function($query){
$query->withCount('item');
}])
->get()
->each(function($parentCategory){
// if you wants calculate sum child category item count and assign to parent category item_count.
$parentCategory->item_count = $parentCategory->children->sum(function ($child) { return isset($child->item_count)?$child->item_count:0;});
});
return view('frontend.home', compact('allCategories'));
In this query only one query will be executed and it return all of your needs.
And In Blade View file
#foreach($allCategories as $category)
{!!$category->title!!} ({!! $category->item_count!!})
<p class="card-text">
#foreach($category->children as $subcategory)
{!!$subcategory->title!!} {!! $subcategory->item_count !!}
#endforeach
</p>
View Category
#endforeach

Related

stuck at DB query, laravel

I need your help...
Can't figure out where the problem is.
I am trying to show all products of a subcategory.Sometimes it shows the first or the last record. Then it repeats many times the same record( as the cycle is).
category: id, name, visible
products:id, name,
category_products:id, id_product, id_category
Route::get('navigation/{id}',function($id){
$prods= \App\Products_to_Categories::where('id_category',$id)->get();
$products=array();
foreach ($prods as $prod)
{
$products[] = \App\Products::find($prod->id_product)->
where('visible','yes')
-> where('delete','no')->first();
}
return view('subcategories.order_products',
['products'=>$products ]);}
View blade
<div class="col-md-6 col-md-offset-1">
<ul id="sortable">
#foreach($products as $product)
<li class="ui-state-default" id="{{ $product->id}}"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span> {{$product->name}}</li>
#endforeach
</ul>
</div>
It looks like products and categories are related through the join table category_products, so you can setup a belongsToMany() relationship and query from Category to Product without looping over the join table.
https://laravel.com/docs/5.7/eloquent-relationships#many-to-many
Category model:
public function products()
{
return $this->belongsToMany(\App\Products::class, 'category_products', 'id_category', 'id_product');
}
Products model:
public function categories()
{
return $this->belongsToMany(\App\Category::class, 'category_products', 'id_product', 'id_category');
}
Controller code:
$category = Category::find($id);
$products = $category->products()
->where('visible', 'yes')
->where('delete', 'no')
// ->inRandomOrder() // un-comment this if you want results in random order
->get();
Try this in Laravel >= 5.2: :
$prods= \App\Products_to_Categories::where('id_category',$id)->get();
$products=array();
$whereIn = array();
foreach ($prods as $prod)
{
$whereIn[] = $prod->id_product;
}
$products[] = \App\Products::find($prod->id_product)
->where('visible','yes')
-> where('delete','no')
->whereIn('id', $whereIn)
->orderByRaw('RAND()')
->get();
This will give you the list of products of a specific category in random order.
Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();
Laravel 3:
User::order_by(DB::raw('RAND()'))->get();
source :
Laravel - Eloquent or Fluent random row

Get the id from one to many modal - Laravel

I need to get the list of product categories from the table.
2 tables in total. tblProduct & tblProductCatLink
1 product can have many product category link.
tblProductCatLink consists of product_id, category_id
Now from my controller & view, i want to get the list of categories belong to one product.
Product.php
public function productcategorylink(){
return $this->HasMany('App\ProductCategoryLink', 'product_id', 'id');
}
ProductCategoryLink.php
public function projects(){
return $this->hasMany('App\Project', 'id', 'product_id');
}
Controller
foreach ($projects as $project) {
foreach ($project->productcategorylink as $value) {
echo $value->category_id;
}
}
The above code is returning first row of category for the product only. I had 3 rows of records for product 297 in my DB.
I need to access the product category link from the view while I looping the product data
In a controller:
$products = Product::with('productcategorylink')->get();
In view:
#foreach ($products as $product)
#foreach ($product->productcategorylink as $link)
{{ $link->category_id }}
#endforeach
#endforeach
You need to call productcategorylink and projects. So it would be
$projects = projects();
foreach ($projects as $project) {
$productCategoryLink = $project->productcategorylink();
foreach ($productCategoryLink as $value) {
echo $value->category_id;
}
}

Hiding empty categories in Laravel

How can I hide empty categories when I query to display them? Empty categories are those that no products are assigned to them..
Here is my controller
public function showSubCats($categoryId) {
$subcats = SubCategories::where('category_id', '=', $categoryId)->get();
return View::make('site.subcategory', [
'subcats' => $subcats
]);
}
Here is the view
#if(count($subcats) > 0)
<div class="row">
#foreach($subcats as $i => $subcategory)
// display categories
#endforeach
#else
There is no products assigned to this category
</div>
#endif
This is my SubCategories model
public function products()
{
return $this->hasMany('Product', 'category_id');
}
public function subcategories()
{
return $this->hasMany('SubCategories', 'category_id');
}
public function lowestProduct() {
return $this->products()->selectRaw('*, max(price) as aggregate')
->groupBy('products.product_id')->orderBy('aggregate');
}
In product table I have column which is sub_cat_id and holds category in which is assigned. If is 0 is not assigned to any category.
How can I hide empty categories now?
You should use where in addition to your model
return $this->hasMany('Action')->where('sub_cat_id', 1);
Note :
I believe that you neeed to take the records only that has sub_cat_id as 1. If not change it to 0 or accordingly.
Hope this helps you

Laravel 5 - Count the number of posts that are assigned to each category in a blog

I was wondering what the cleanest way was to count the number of posts that are connected to a category in my blog.
Here is how the table relationship is set up.
What I have is a hasMany relationship from the Category to the Post models like this:
In Categories Model
public function blog_posts()
{
return $this->hasMany('App\Http\Models\Blog_Post', 'category_id');
}
And in the Blog_Post Model
public function blog_categories()
{
return $this->belongsTo('App\Http\Models\BlogCategories', 'category_id');
}
In effect all I want to do is be able to return to my view the total number of posts that each category has as shown below. Where x is the number of posts within each category.
cat1 (x)
cat2 (x)
cat3 (x)
It's not hard to count I know however as I only want a count I do not want to also retrieve the records as they are not required and I also do not want to create more queries than is necessary.
I have not completed the view as yet but probably a start would be to pass through the categories in a loop to display each and add the count at the same time?
#foreach ($categories as $category)
{!! $category->name !!} - {!! Count of posts here !!}
#endforeach
Hopefully that is clear(ish)!
Eager load the relation in your controller:
public function index()
{
$categories = Category::with('blog_posts')->get();
return view('categories.index', compact('categories'));
}
You can then use the count() method on the blog_posts relation when looping over categories in your view:
#foreach ($categories as $category)
<li>{{ $category->name }} ({{ $category->blog_posts->count() }})</li>
#endforeach
EDIT: Since Laravel 5.3, you can use withCount() to load counts of relations, i.e.
$categories = Category::withCount('blog_posts')->get();
This will make the count available via a property:
foreach ($categories as $category) {
$blog_posts_count = $category->blog_posts_count;
}
The nicest way to do it with eager loading support I know is to create a separate relation with the post count. Check this out:
public function blog_posts_count() {
return $this->hasOne('App\Http\Models\Blog_Post', 'category_id')
->selectRaw('category_id, count(*) as aggregate')
->groupBy('category_id');
}
public function getBlogPostsCountAttribute() {
if(!array_key_exists('blog_posts_count', $this->relations))
$this->load('blog_posts_count');
$related = $this->getRelation('blog_posts_count');
return $related ? (int) $related->aggregate : 0;
}
Usage is simple:
{{ $category->blog_posts_count }}

one to many relationship help in laravel 4

I am trying to create a relationship between Category and Product but somehow I couldn't use the category to connect into the product table and prints out the product names and instead I get the category's name
in my database
Table Name: products
Columns: id, name, price, category_id, description
Table Name: categories
Columns: id, name, description
in products table
id: 1
name: product1
price: 10
category_id: 1
description: p1
---------------
id: 2
name: product2
price: 10
category_id: 1
description: p2
in categories table
id: 1
name: category1
description: c1
---------------
id: 2
name: category2
description: c2
Product.php inside models folder
class Product extends Eloquent
{
protected $product = 'products';
public function category()
{
return $this->belongsTo('Category');
}
}
Category.php inside models folder
class Category extends Eloquent
{
protected $category = 'categories';
public function product()
{
return $this->hasMany('Product', 'category_id');
}
}
ProfileController.php in controller folder
class ProfileController extends BaseController
{
public function user($username)
{
$user = User::where('username', '=', $username);
if ($user->count())
{
$user = $user->first();
$title = 'User Profile';
$category = Category::find(1);
$products = Category::find(1)->name;
return View::make('profile.user', compact('user', 'title', 'category', 'products'));
}
return 'User Not Found. Please Create an Account';
}
}
user.blade.php inside profile folder which is inside view folder
#extends('layouts.master')
#section('content')
{{ Auth::user()->username }}
<br>
{{ Auth::user()->email }}
<br>
<h1>{{ 'Category name: '. $category->name }}</h1>
<br>
<h3>{{ 'Category Description: ', $category->description }}</h3>
<br>
{{ $products }}
#stop
at first where the {{$products}} I used a foreach loop
#foreach($products as $product)
{{$product}}
#endforeach
but then I got this error
ErrorException
Invalid argument supplied for foreach() (View: J:\wamp\www\test\app\views\profile\user.blade.php)
so I tried var_dump($products) and realized $products gives out category1 which is the name of the category but what I want is printing the name of all the products which has category_id 1
Can someone give me a hand with this? Did I mess something up with the relationship or I did something stupid with the codes?
In your controller:
$category = Category::find(1);
$products = $category->product;
Then in your template you can use:
#foreach ($products as $product)
{{ $product->name }}
#endforeach
Better yet you could use eager loading and forget about assigning products manually:
Controller:
$category = Category::with('product')->where('id', 1)->first();
Template:
#foreach ($category->product as $product)
{{ $product->name }}
#endforeach
PS: Read more on eager loading here: http://laravel.com/docs/eloquent#eager-loading
in order to prevent the dreaded N + 1 query problem!

Categories