How to count how many articles belongs which category? - laravel

I have this relationships:
ARTICLES
public function category()
{
return $this->belongsTo('App\Models\Categories');
}
CATEGORY have translations
public function c_translations()
{
return $this->hasMany('App\Models\CategoryTranslations', 'category_id');
}
In articles i have category id, also in translations i have category_id. So how can i count how many articles have each category. Any suggestion?
$articles = Articles::all();
foreach($articles as $article ){
$articles_category = Articles::where('id',$article->id)->withCount('category')->first();
}
I tried this but always get 0 for all of categories

Define a hasMany relation in your Category model as:
public function articles()
{
return $this->hasMany('App\Models\Article');
}
Then you can use withCount to query it as:
$categories = Category::withCount('articles')->get();
Pass it to your view and then you can access the no. of articles of category as:
#foreach ($categories as $category)
<li>{{ category->title }}</li>
<li>{{ category->articles_count }}</li>
#endforeach

Use withCount() method to count relation.
Model::where('id', $id)->withCount('relation')->first();
If you want to count the number of results from a relationship without actually loading them you may use the withCount method, which will place a {relation}_count column on your resulting models.

I think you should use a group by statement.
You select category_id,COUNT(*) FROM articles GROUP BY category_id
This will return the number of articles for each category_id

Related

How to convert Database Query Builder to Database Eloquent?

How to convert Database Query Builder to Database Eloquent?
$products = DB::table('carts')
->join('products','.carts.product_id','=','products.id')
->where('carts.user_id',$userID) ->select('products.*')
->get();
As you've provided very little information to assist you with, some assumptions are going to be made such as naming conventions and relationship types.
Product.php
Add a carts relationship to your Product model. This assumes a Product can belong to many Carts.
public function carts()
{
return $this->belongsToMany(Cart::class);
}
Cart.php
Add a products relationship to your Cart model. This assumes a Cart can have many Products.
public function products()
{
return $this->belongsToMany(Product::class);
}
Create a pivot table which will maintain the relationships between Carts and Products:
php artisan make:migration create_cart_product_table
Then add your relationship foreign keys to the migration:
public function up()
{
Schema::create('cart_product', function (Blueprint $table) {
$table->id();
$table->foreignId('cart_id')->constrained();
$table->foreignId('product_id')->constrained();
$table->timestamps();
});
}
To add Products to a Cart, you can use the attach or sync methods, for example:
$products = Product::inRandomOrder()->take(5)->pluck('id');
Cart::create(['user_id' => 1])->products()->attach($products);
The above will get 5 Products (at random) from your products table, then create a new Cart with the given user id and attach those Products to the Cart.
To retrieve a Cart and it's associated Products, you would do the following:
$cart = Cart::where('id', $id)->with('products');
The $cart variable can be passed to a view or in a json response where after you can iterate over the Products in the Cart.
$cart = Cart::where('id', $id)->with('products');
return view('cart', compact('cart'));
blade view
<ul>
#foreach ($cart->products as $product)
<li>{{ $product->name }}</li>
#endforeach
</ul>
If you want to get all the Cart records for a given User, you would do the following:
$carts = Cart::where('user_id', $id)->with('products')->get();
return view('carts', compact('carts'));
blade view
#foreach ($carts as $cart)
{{ $cart->id }}
<ul>
#foreach ($cart->products as $product)
<li>{{ $product->name }}</li>
#endforeach
</ul>
<hr />
#endforeach
Or something to that effect.

Show many products from a category from many-to-many relationship in laravel

So I’m making a catalogue using Laravel 7.* and I have a problem.
I have many products and many categories. I have created a many-to-many relationship so a product can be in many categories.
Now, what I am trying to do is to show in a page each category with related products, but obviously I am doing something wrong.
Below you may see some code:
Product.php:
public function categories()
{
return $this->belongsToMany(Category::class);
}
Category.php:
public function product()
{
return $this->belongsToMany(Product::class);
}
Show.blade.php
#php
$products = \App\Product::with('categories')->find(1);
#endphp
#foreach ($products as $id)
{{ $id->name }}<br>
#endforeach
Any help please?
Fixed it.
I fetched categories in controller and send to view. Then for each category displayed each product.
Get all the categories and show products related to them.
#php
$categories= \App\Category::all();
#endphp
#foreach($categories as $category)
#foreach($category->product as $product)
{{$product->name}}
#endforeach
#endforeach
You need also Id of category that you want to show products related to it.
According To This answer
Try this:
$category_id = 1; // Desired Category Id
$products = \App\Product::whereHas('categories', function($query) use ($category_id) {
$query->where('category_id', $category_id);
})->paginate();
I also added pagination.

Laravel - virtual column id -> uuid

I have two models:
Ingredient, Category
Each ingredient has a category id, each category has many ingredients.
The problem is that I use auto-increment ids for joins and queries internally, but only show UUIDs to end users.
So the Ingredient table looks like this:
id uuid name category_id
And the category table looks like this:
id uuid name
My data in ingredients looks like this:
id: 1,uuid:{a uuid}, name: Ingredient A, category_id: 1
When I do a Ingredient::get(), I want to return this:
uuid: {ingredient uuid}, name: Ingredient A, category_uuid: {the category uuid}
Based on what I am learning about Laravel, you can use accessors and mutators.
I set up
protected $appends = [
'category_uuid'
];
and
public function category()
{
return $this->belongsTo(Category::class);
}
public function getCategoryUuidAttribute()
{
return $this->category()->uuid;
}
But I get this error:
message: "Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$uuid"
What am I doing wrong?
It seems the issue was adding ->first() to the method chain, and that handled it.
So it becomes:
public function getCategoryUuidAttribute()
{
return $this->category()->first()->uuid;
}
You can also achieve this using Query Builder:
public function index()
{
$ingredients = DB::table('ingredients')
->join('categories', 'ingredients.category_id', 'categories.id')
->select('ingredients.*', 'categories.uuid as c_uuid')
->get();
return view('index', compact('ingredients'));
}
#foreach($ingredients as $ingredient)
<ul>
<li>{{ $ingredient->uuid }}</li>
<li>{{ $ingredient->name }}</li>
<li>{{ $ingredient->c_uuid }}</li>
</ul>
#endforeach

accessing collections within collections laravel 5

I have a table of "rosters" that's pretty much strictly foreign keys. It acceses the "schools" table, "courses" table, and "students" table. So essentially, a 'student' takes a 'course' at a 'school'. My RostersController has this
public function show($id)
{
$roster = Roster::where('course_id', $id);
return view('roster')->with('roster', $roster);
}
My Roster Model is:
public function students()
{
return $this->hasMany('App\Student');
}
My student Model is:
public function roster()
{
return $this->belongsTo('App\Roster');
}
my view is this:
#foreach ($roster as $child)
<p>{{$child->id}}</p>
<p>{{$child->students->first_name}}</p>
#endforeach
The rosters table just saves the student_id rather than all of the student's data that is already in the 'students' table. So i'm trying to access the students table from this relation but when i run this, it tells me that anything related to the students table is 'not on this collection'. I know that I could do things this way if i was working with a hasOne relationship, but how can i accomplish this with a hasMany to output the students table value in each row?
You should try this
public function show($id)
{
$roster = Roster::with('students')->where('course_id', $id);
return view('roster')->with('roster', $roster);
}
Try this
Roster.php
public function show($id)
{
$roster = Roster::with('students')->where('course_id', $id)->get(); // load the students
return view('roster')->with('roster', $roster);
}
On the view
#foreach ($roster as $child)
<p>{{$child->id}}</p>
<p>
<!-- Loop through the stundents since this returns an collection of students and not just one -->
#foreach($child->students as $student)
{{$student->first_name}} <br>
#endforeach
</p>
#endforeach
Check this for more information on eager loading
The $child->students is a collection. So, you need to use another foreach loop inside the first one.
Your code should look like this:
#foreach ($roster as $child)
<p>{{$child->id}}</p>
#foreach($child->students as $student)
<p>{{$student->first_name}}</p>
<p>{{$student->age}}</p>
<p>{{$sutdent->another_column_in_students_table}}</p>
#endforeach
<p>{{$child->any_other_column_in_roster_table_if_needed}}</p>
#endforeach
So, your first issue is, that
$roster = Roster::where('course_id', $id);
will just return a QueryBuilder instance, you have to use
$roster = Roster::where('course_id', $id)->get();
then for sure, students is a collection, you have to iterate over it like this:
#foreach ($child->students as $student)
{{ $student->yourProperty}} <br>
#endforeach
Update:
I saw you know already about that when to use get() in query laravel 5

OrderBy on Eloquent whereHas relationship

I have a simple page which lists counties and there related items under headings. These items need to be approved, hence the whereHas method.
I currently have the following eloquent query;
$counties = County::whereHas('items', function ($query) {
$query->where('approved', 1);
})->get();
The items returned are currently ordered by their primary field id (it would seem), however I want to list these items alphabetically by their name field.
I have tried the following query, but this does change anything. Any advice would be appreciated?
$counties = County::whereHas('items', function ($query) {
$query->where('approved', 1)->orderBy('name');
})->get();
$counties = County::whereHas('items', function ($query) {
$query->where('approved', 1);
})->orderBy('name')->get();
I don't think you can order on the subquery, it should be before the ->get
when you want to display the result , try this :
#foreach($counties as $county)
#foreach($county->items->orderBy('name') as $item)
{{ $item->name }}
#endforeach
#endforeach
Or in your County Models :
public function approvedItems(){
return $this->hasMany(Item::class)->where('approved', 1)->orderBy('name');
}
and then :
controller :
$counties = County::whereHas('approvedItems')->get();
view :
#foreach($counties as $county)
#foreach($county->approvedItems as $item)
{{ $item->name }}
#endforeach
#endforeach
Try to work with your models and relationships for having the lightest controller you can, you will gain in lisibility
To keep it eloquent, you can put it in the relation, in the Model class:
public function reviews()
{
return $this->hasMany(Review::class)->orderBy('id','desc');
}
https://laravel.io/forum/09-14-2015-ordering-a-collection-by-the-related-items
Might be late, but hopefully someone stumbles on this (it's the first in google search)
$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');

Resources