Nested foreach loops duplicate rows (Laravel 9) - php

I am currently working on my first real project with Laravel 9. I have come to a problem that I can't solve. I have two tables Categories and Articles and the they are connected with the field id (categories table) and category_id (articles table).
In my CategoryController:
public function categories(){
$categories = Category::all();
$articles = Article::all();
return view('category.categories')->with('cats',$categories)->with('arts',$articles);
}
My Blade view is setup like this:
<ul>
#foreach($cats as $cat)
<li>{{ $cat->name}}
<ul>
#foreach($arts as $art)
#if($cat->id == $art->category_id)
<li>{{ $art->title }}</li>
#else
<li>No articles</li>
#endif
#endforeach
</ul>
</li>
#endforeach
When I check in I get this
Category 1
Article title 1
No articles
No articles
No articles
No articles
Category 2
No articles
Article title 2
No articles
No articles
No articles
Category 3
No articles
No articles
Article title 3
No articles
No articles
Category 4
No articles
No articles
No articles
Article title 4
No articles
Category 5
No articles
No articles
No articles
No articles
No articles
How can I solve this so it only says once No article under Category 5

I would make sure your relationships in your models are set up.
In your Category model:
public function articles()
{
return $this->hasMany(Article::class);
}
Then, in your CategoryController:
public function categories(){
$categories = Category::with('articles')->get();
return view('category.categories')->with('cats',$categories);
}
I'm not quite sure about the blade part, but you should be able to do:
<ul>
#foreach($cats as $cat)
<li>{{ $cat->name}}</li>
#if(empty($cat->articles))
<li>No articles</li>
#else
<ul>
#foreach($cat->articles as $art)
<li>{{ $art->title }}</li>
#endforeach
</ul>
#endif
#endforeach
</ul>

Related

Getting user categories sub categories

When user registers then he haves 2 steps.
He must choose categories what is he interest of and then in step two he must choose sub categories of categories what he chose in step one.
In step one he can chose and i save data but in step two i can't get sub categories what he chose.
In my categories table i'm having parent_id column so i for example when he chose category_id one in step two it must show categories where parent_id is 2
I have pivot table CategoryUser where he saves step one user_id and category_id
In controller i don't have nothing ))
public function stepTwoIndex()
{
$users = User::all();
return view('auth/student/step-two')->with('users', $users);
}
In blade
#foreach($users as $user)
#foreach($user->categories()->where('parent_id', $user->course_category_id)->get() as $category)
<div class="subcategory-checkboxs row">
<div class="main-sub col-lg-3">
<input class="main-category-checkbox" type="checkbox" id="main-subcategory">
<label class="main-category-checkbox" for="main-subcategory">{{ $category->name }}</label>
</div>
</div>
#endforeach
#endforeach
I'm new in this so it's very hard to me to do this i'm searching all day how to do this but... (

How to use whereNotNull in controller while using with (' Many-to-many relationships') to show on the blade view?

I try to show the 'categories' from Many to Many relationships and use
whereNotNull at the same time but when I use whereNotNull to check that the users have approved then the categories from the relationships are disappeared in the blade view.
If I have not put whereNotNull. The list of users who are vendors still appears (approved and waiting for approval both of them are showing in the view with the category relationships). When I use whereNotNull the blade view will show only approved users without category relationships.
The explanation pictures.
When use whereNotNull click!
When not use whereNotNull click!
This is the view that I want to show the categories from the relationships.
#if(count($user->categories) > 0)
#foreach ($user->categories as $category)
<span class="badge badge-pill badge-info p-2 m-1">{{ $category->name }}</span>
#endforeach
#endif
The UserController
public function index()
{
$users = User::with('categories') // Eager loading
->where('role', 'vendor')
->whereNotNull('approved_at') //If I put whereNotNull the categories will now showing
->get(); but If I delete it, the relationships will appear in the
view again.
return view('admin.vendorDashboard')
->with('categories', Categories::all())
->with('users', $users);
}
}
User Model
public function categories()
{
return $this->BelongsToMany(Categories::class);
}
Categories Model
public function users()
{
return $this->BelongsToMany(User::class);
}
User Table
Id
User
Approved_at
Role
1
A
2020-12-24 18:40:59
Vendor
2
B
2020-12-24 18:39:59
Vendor
Category Table
Id
Category
1
C
2
D
user_category table
Id
user_id
category_id
1
1
1
2
1
2
Thank you in advance.
p.s. sorry for my bad English.

Laravel 5.7 - "orderBy" Not Sorting Results

I have three models related through hasMany relationship: Course/Lesson/Article - A Course hasMany Lessons which hasMany Articles.
I have an int column in my articles table named pos (short for position) and I want to order the articles by it.
I am using the following query in my CoursesController, but it's not sorting the articles by this pos attribute:
Code:
public function show(Course $course, Lesson $lessons, Article $articles)
{
$articles = $lesson->articles()->orderBy('pos', 'asc')->get();
return view('users.courses.show', compact('course', 'lessons', 'articles'));
}
I'm using a foreach loop in blade:
#foreach($lesson->articles as $article)
{{ $article->title }}
#endforeach
Any help would be appreciated!
Laravel debugbar shows the following result:
select * from articles where slug = 'this-is-article-one' limit 1
13.27ms\vendor\laravel\framework\src\Illuminate\Routing\ImplicitRouteBinding.php:35
select * from articles where lesson_id = 1 and pos < 2 order by pos desc limit 1 660μs\app\Http\Controllers\Users\ArticlesController.php:55
select * from articles where lesson_id = 1 and pos > 2 order by pos asc limit 1 520μs \app\Http\Controllers\Users\ArticlesController.php:59
select * from courses where courses.id = 2 limit 1 610μs view::users.articles.show:7
select * from lessons where lessons.id = 1 limit 1 530μs
view::users.articles.show:8
select * from articles where articles.lesson_id = 1 and articles.lesson_id is not null
When you call $lesson->articles again in the show view, basically you make a new DB call. To get the correct values, use the variable $articles:
#foreach($articles as $article)
{{ $article->title }}
#endforeach
If you want to continue using your lesson object in your view, use sortBy:
#foreach($lesson->articles->sortBy('pos') as $article)
{{ $article->title }}
#endforeach
I will suggest to extend you relationship with orderBy()
<?php
public function articles(){
return $this->hasMany('App\Articles')->orderBy('pos','asc');
}

count post with all categories in laravel 5

hello I have two tables one is categories another is ads_listings. In categories table there are 4 columns id, parent_category_id, category_slug, category_title. Here parent_category_id 0 indicates main category and rest of the thing indicates sub category. user post store in ads_listings table. Now I want to find post with specific categories like this
vehicles(3)
cars(2)
motorbike(1)
cycle(0)
here the problem is my code found only subcategories which have posts. my controller code is
public function countListingsByCategories()
{
return DB::table("ads_listings")
->select("categories.category_title",DB::raw("COUNT(ads_listings.category_id) as num_listings"))
->join("categories", "categories.id","=","ads_listings.category_id")
->groupBy("ads_listings.category_id")
->get();
}
views code is:
<ul class="row catelist">
#if(isset($categoriesNumListings) && count($categoriesNumListings))
#foreach($categoriesNumListings as $categoriesNumListings)
<li class="col-md-12">{{ $categoriesNumListings->category_title }} <span>({{ $categoriesNumListings->num_listings }}Listings )</span></li>
#endforeach
#endif
</ul>
my Category table is:
ads_listing table is:
I think the problem is that you are counting ad_listings when you primarily want to count categories and get the number of ad_listings, I would do something like:
Second shot :)
public function countListingsByCategories()
{
return DB::table("categories")
->select("categories.category_title",
DB::raw("categories.title,
CASE
WHEN (categories.parent_id = 0)
THEN (SELECT count(ads_listings.category_id)
FROM ads_listings
WHERE ads_listings.category_id in
(SELECT subcategory.id
FROM categories subcategory
WHERE subcategory.parent_id = categories.id))
ELSE (SELECT COUNT(ads_listings.category_id)
FROM ads_listings
WHERE ads_listings.category_id = categories.id)
END as numberOfPosts,
CASE
WHEN (categories.parent_id = 0)
THEN (select 'Category')
ELSE (select 'subCategory')
END as type
FROM categories"))
->get();
}

Count database column text values - Laravel

So, I have a database table that looks something like this:
id | title | category | author | post | created_at | updated_at
The category column is a text value, so it currently has values such as 'Tech', 'Web', and 'Animal'. What I need to do, is to count each category value in the category column and have an output such as:
Tech (2)
Animal (2)
Web (1)
Now, I do kind of have it working. It currently looks like:
Tech (1) (1)
Animal (1) (1)
Web (1)
The query in my controller is:
$categoryCount = Post::select(DB::raw('count(*) as cat_count, category'))
->groupBy('category')
->count();
My view currently looks like:
#if(count($category) > 0)
#foreach($category as $cat)
<a href="{{ URL('category/'.str_replace(' ', '-', $cat->name)) }}"
class="list-group-item">{{ $cat->name }}
#foreach($posts as $post)
#if($post->category == $cat->name)
({{ $categoryCount }})
#endif
#endforeach
</a>
#endforeach
#endif
I am quite new to Laravel itself, so I'm still learning. Any help to achieve what I want would be appreciated.
You do a DB raw count and then again a count. It will indeed then return always one. Change your query:
$categoryCount = Post::select(DB::raw('count(*) as cat_count, category'))
->groupBy('category')
->get();
And your results should be different. This has by the way nothing to do with Laravel, merely that you count the count :-)

Categories