How to count average value for each user? - laravel

I have two tables: users, comments.
Each user has some comments.
I do request like as:
$users = User:with('comments')->get();
How can I count the average value in field comments.rate where users.id = comments.user_id
In result I should get collection with all rows wityh user information and field avg_rate
I tried to use ->avg(), but it returns only one row, not for each
I have own solution, but I have desire to move this code in model:
{{$users->reviewsAverage()->first()->avg("rate")}}
Model:
public function reviewsAverage()
{
return $this->hasMany('App\Review', 'user_id', 'id'); //->first()->avg('rate');
}

Have two functions one for the relationship and he other for the average function
public function comments()
{
return $this->hasManyThrough('App\Comment', 'id');
}
public function averageRating()
{
return $this->comments()->selectRaw('avg(rate) as average_rate, comment_id')
->groupBy('comment_id');
}
Then go ahead and query like this
foreach($users as $user){
$rate = $user->averageRate();
}

Related

get posts where relationship count is equel to post's attribute

I have a model "Post" which has a field "daily" in the database.
$table->integer('daily'); // could be anything
The Model "Post" has a relationship to the model "Comments".
public function comments() {
return $this->hasMany(Comment::class);
}
public function completed() {
return $this->hasMany(Comment::class)->completed();
}
Comments model
public function scopeCompleted($query) {
return $query->....?
}
I want to get all user's posts where it's comments count are equal to the post's 'daily' field. For example: if the post's daily field is '5' and there are 5 comments to this posts, I want to see this post in the returned lists, otherwise don't return it.
I know I can get all of them and do it with loop, but I wanna know if there is any way to do this with eloquent only.
Try this
$user=User::with('posts','posts.comments')
->whereHas('posts.comments',function ($query){
//if any additional filters
},'=',DB::raw('posts.daily'))
->get();
or if not needed additional query then
$user=User::with('posts','posts.comments')
->whereHas('posts.comments',null,'=',DB::raw('posts.daily'))
->get();
Got it working like this
public function scopeCompleted($query) {
return $query->has('comments', '=', DB::raw('posts.comments'));
}

How to order by column in nested level relationship in Laravel and get first order by?

I have two model.finance has many price.i want to get just one price (last record according to time) for every finance.so used function and order by and first of each orderby.but this just works for first finance and the other i get null in the with relation.
public function prices()
{
return $this->hasMany(Price::class, 'finance_id');
}
public function finances()
{
return $this->belongsTo(Finance::class, 'finance_id');
}
$finances = Finance::with(['prices' => function ($query) {
$query->orderBy('created_at', 'desc')->first();
}])->get();
Create new relationship in your Finance model to get latest price:
public function latestPrice()
{
return $this->hasOne(Price::class)->latest();
}
Change your query as below:
$finances = Finance::with('latestPrice')->get();

How to get top 10 category list in laravel eloquent query

i have three table one is category table and another is product table and one more product_to_category table, and it has only product_id and category_id column.
Now i want to get top 10 categories with maximum number of product, with details of 10 products from each category.
What i wrote is
$result = ProductToCategory::groupBy('category_id')->with(['product',function($q){
$q->take(10);
}])->orderBy('category_id)->take(10);
But this is not working.How to write this query properly
Can anyone please help. ty
Model relations
For Product model
public function category(){
return $this->belongsTo(ProductToCategory::class);
}
For Category model
public function products()
{
return $this->hasMany(ProductToCategory::class);
}
For ProductToCategory model
public function product()
{
return $this->hasMany(Product::class);
}
public function category()
{
return $this->belongsTo(Category::class);
}
The most efficient way would be using a raw SQL query because you can't filter products by using eager loading constraint.
But if you want an Eloquent solution anyway, define the relationships:
In the Product model:
public function categories()
{
return $this->belongsToMany(Category::class, 'product_to_category');
}
And in the Category model:
public function products()
{
return $this->belongsToMany(Product::class, 'product_to_category');
}
Then you'll have two options, both have their pros and cons:
1. This code will execute just 2 queries but will use more memory. You could get top ten categories with their products:
$categories = Category::withCount('products')->latest('products_count')->take(10)->with('products')->get();
And then keep only first ten products:
$categories->transform(function($category) {
$topProducts = $category->products->take(10);
unset($category->products);
$category->products = $topProducts;
return $category;
});
2. This solution will create 12 queries but will save the memory:
$categories = Category::withCount('products')->latest('products_count')->take(10)->get();
$categories->transform(function($category) {
$category->products = Product::whereHas('categories', function($q) use($category) {
$q->where('id', $category->id);
})
->take(10)
->get();
return $category;
});
Here is the DB facade version:
$tenPopularTags = DB::table('product_to_category')
->join('category', 'product_to_category.category_id', '=', 'category.id')
->select(DB::raw('count(product_to_category.category_id) as repetition, question_tag.tag_id'))
->groupBy('product_to_category.category_id')
->orderBy('repetition', 'desc')->take(10)
->get();
However I like #Alexey Mezenin way of doing it. Because that is the cleaner way have customized it a bit:
$tenCategories = Category::withCount('products')->orderBy('questions_count', 'DESC')->take(10)->get();
Have used both in my project blog with post and categories relationship and it works!

Ordering data from a table with the help of other table by using relationships with laravel?

I have the controller with the query:
$Comments = Comment::orderBy('id_parent', 'asc')->get();
And I have the Comment model:
class comment extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
public function votes()
{
return $this->hasMany('App\Vote', 'comment_id', 'id_comment');
}
}
I want to retrieve the comments data sorted in a specific way, every comment has multiply votes voted by different users, so the count('vote') is the number of votes for each comment. The problem is that I am stuck with how to call the specific votes function in the model so that it can count the column vote and order it either asc or desc.
That in the end I can have the $Comments sorted also by the total number of votes.
You can try as:
$Comments = Comment::withCount('votes')->orderBy('votes_count', 'asc')->get();
withCount() method is used when you want to count the number of results from a relationship without actually loading them, which will place a {relation}_count column on your resulting models.
Using sortBy:
$comments=Comment::with('votes')->get()->sortBydesc('votes');
foreach($comments as $comment)
{
echo $comment->votes->count('vote');
}

laravel eloquent left join not outputting

I'm trying to achieve this
SELECT *
FROM pending
LEFT JOIN users ON pending.user_id = users.id
WHERE pending.school_id = '1'
Which produces two results of the two tables combined with the users details output.
Pending Model
public function users(){
return $this->belongsTo('User');
}
public function school(){
return $this->belongsTo('School');
}
User model
public function pending(){
return $this->hasMany('Pending','user_id');
}
School Model
public function pending(){
return $this->hasMany('Pending','school_id');
}
Controller
$pending_user = Pending::with('users')->where('school_id', '=', '1')->get();
This retrieves an array of the two records but a null result in the user array.
"users":null
Any help appreciated.
I have decided to go with this
$pending_user = Pending::select('first_name','last_name','user_id','how')->where('school_id', '=', '1')->leftjoin('users','pending.user_id','=','users.id')->get();

Resources