laravel - eloquent - get sum of related model specific column - laravel

assuming that I have the table
orders
with fields
id, userId, amount, description
and the table
user
with various fields
how if I wand to get all the users (with all its fields) and also the sum of the "amount" column of the orders related to that user?
assuming that I have:
user:{id:15,firstName:jim,lastName:morrison,gender:male}
and
order:{id:1,userId:15,amount:10,description:"order xxx"},
order:{id:3,userId:15,amount:40,description:"order yyy"}
I would like to receive:
user:{id:15,firstName:jim,lastName:morrison,gender:male,orderAmount:50}
Of course I would like to avoid the foreach statement.
I've setted this on my user model
public function userOrder (){
return $this->hasMany('Order', 'userId');
}
And I've tryed this:
return $this->hasMany('Order', 'userId')->sum('amount');
without any luck...

Some thaughts and hopefully an answer to your question:
I would rename the user table to users to stick to laravel conventions.
http://laravel.com/docs/4.2/eloquent#basic-usage
I would name the method in the User model orders
public function orders()
{
return $this->hasMany('Order', 'userId');
}
To query a user, his orders and sum afterwards his orders amount values:
$userdata = User::with( 'orders' )->where( 'userId', 15 )->first();
$sum = $userdata[ 'orders' ]->sum( 'amount' );

Related

Laravel 5.2 Eloquent ORM to get data from 3 tables

I have the following tables. users, user_details and client_teams. Each user has one details and each user can have many teams. schema for users:
id, name, email,parent_user_id
user_details:
id, user_id, client_team_id
client_teams:
id, user_id, team_name,status
In user_model i have the following relations:
public function userDetails(){
return $this->belongsTo('App\Models\UserDetails','id','user_id');
}
public function clientTeamList(){
return $this->hasMany('App\Models\ClientTeams','user_id','id');
}
In user_details model i have the following relation:
public function clientMemberTeam(){
return $this->belongsTo('App\Models\ClientTeams','client_team_id');
}
I want to be show the list of users who have a specific team ID and created by a specific user. The query that i am using is this:
$userCollections=Users::where([
['users.status','!=','DELETE'],
['users.parent_user_id',$clientId],
['users.id','!=',$loginUser->id]
])
->with([
'userDetails'=>function($query) {
$query->where('client_team_id',1);
}
]);
This is giving me all records for this user, Whereas i want to match by client_team_id and user_id
You need to use whereHas and orWhereHas methods to put "where" conditions on your has queries.
Please look into https://laravel.com/docs/8.x/eloquent-relationships
$userCollections = Users::where([['users.status', '!=', 'DELETE'],
['users.parent_user_id', $clientId],['users.id', '!=', $loginUser->id]
])
->whereHas('userDetails' => function ($query) {
$query->where('client_team_id', 1);
})->get();

Laravel: Property [user] does not exist on this collection instance

In Laravel, I've Orders model where each order belongs to only one user,
I want to return only user names and orders ids when I fetch the orders, So in my OrdersController I've this function
public function getAllOrders()
{
$orders = Order::all();
return new OrderResource($orders);
}
and in my OrderResource I've
public function toArray($request)
{
return [
'user' => $this->user,
'id' => $this->id,
];
}
I'm getting an error saying Property [user] does not exist on this collection instance.
I think the reason is coming from the fact that $orders is a collection and I should loop through it and get for each order get the user associated with it, but I've no idea how to do that.
Note: I'm using oneToMany and belongsTo on Users and Orders Model. so orders table doesn't have a user column, I want to get the user from the relationship.
When using a collection use like this;
public function getAllOrders()
{
return OrderResource::collection(Order::all());
}
When using a model use like this;
public function getOrder($id)
{
return new OrderResource(Order::find($id));
}
More information in the documentation: https://laravel.com/docs/7.x/eloquent-resources#concept-overview
Note: To avoid N+1 queries, you should get your orders like this; Order::with('user')->get(); instead of Order::all()
The difference is that Order::with('user')->get(); will perform two queries.
select * from orders
select * from users where id in (?, ?, ?, ?, ...)
Whereas Order::all() will perform N+1 queries (N = number of orders)
select * from orders
select * from users where id = ?
select * from users where id = ?
select * from users where id = ?
... and so on

Get only one column from relation

I have found this: Get Specific Columns Using “With()” Function in Laravel Eloquent
but nothing from there did not help.
I have users table, columns: id , name , supplier_id. Table suppliers with columns: id, name.
When I call relation from Model or use eager constraints, relation is empty. When I comment(remove) constraint select(['id']) - results are present, but with all users fields.
$query = Supplier::with(['test_staff_id_only' => function ($query) {
//$query->where('id',8); // works only for testing https://laravel.com/docs/6.x/eloquent-relationships#constraining-eager-loads
// option 1
$query->select(['id']); // not working , no results in // "test_staff_id_only": []
// option 2
//$query->raw('select id from users'); // results with all fields from users table
}])->first();
return $query;
In Supplier model:
public function test_staff_id_only(){
return $this->hasMany(User::class,'supplier_id','id')
//option 3 - if enabled, no results in this relation
->select(['id']);// also tried: ->selectRaw('users.id as uid from users') and ->select('users.id')
}
How can I select only id from users?
in you relation remove select(['id'])
public function test_staff_id_only(){
return $this->hasMany(User::class,'supplier_id','id');
}
now in your code:
$query = Supplier::with(['test_staff_id_only:id,supplier_id'])->first();
There's a pretty simple answer actually. Define your relationship as:
public function users(){
return $this->hasMany(User::class, 'supplier_id', 'id');
}
Now, if you call Supplier::with('users')->get(), you'll get a list of all suppliers with their users, which is close, but a bit bloated. To limit the columns returned in the relationship, use the : modifier:
$suppliersWithUserIds = Supplier::with('users:id')->get();
Now, you will have a list of Supplier models, and each $supplier->users value will only contain the ID.

Laravel, How to retrieve parent records with certain Pivot table values belongsToMany

How can I retrieve all records of my model based on certain ID's in my pivot table?
I have the following 3 tables
users;
id,
name
stats;
id,
name
stats_selected;
user_id,
stats_id
Model
User.php
public function stats()
{
return $this->belongsToMany('App\stats', 'stats_selected', 'user_id', 'stats_id')->withTimestamps();
}
Controller
// Get all users with example of stats ID's
$aFilterWithStatsIDs = [1,10,13];
$oUser = User::with(['stats' => function ($query) use($aFilterWithStatsIDs ) {
$query->whereIn('stats_id', $aFilterWithStatsIDs);
}])
->orderBy('name', 'desc')
->get()
This outputs just all the users. Btw, fetching users with there stats and saving those selected stats into the DB is not a problem. That works fine with the above lines.
But how do I retrieve only the users which has certain stats_id's within them?
But how do I retrieve only the users which has certain stats_id's within them?
Use a whereHas conditional.
User::whereHas('stats', function ($stats) use ($aFilterWithStatsIDs) {
$stats->whereIn('id', $aFilterWithStatsIDs);
});

Count from hasManyThrough relationship with eager loading (need only Count)

I only need the count, don't want to retrive the results or perform query each time for each row. This is why I want eager loading.
I have 3 tables like the following:
Admins
id
Posts
id
admin_id
Comments
id
user_id //nullable (null if comment from admin)
admin_id //nullable (null if comment from user)
news_id
Now I want to retrieve all the posts from a single admin and all the comments count from those posts, without retrieving all the comments for posts, ONLY COUNT of comments,
With eager loading to avoid n+1 query issue;
Here I think we should make a relation to be used with eager loading like the following:
//admin model
public function commentsCountRelation()
{
return $this->hasManyThrough(Comment::class, News::class, 'admin_id', 'news_id')
->selectRaw('news_id, count(*) as count')
->groupBy('news_id');
}
--Look Here I used hasManyThrough relation because, news_id is not in Admins table.
Then I should make an attribute, to access the count easyly, like:
public function getCommentsCountAttribute()
{
return $this->commentsCountRelation->first()->count ?? 0;
}
Then access it like:
$admin = Admin::with('commentsCountRelation')->findOrFail($id);
$admin->commentsCount;
But it always returns null, why is that?
The following works for hasMany & belongsTo, I've used it on my other models like:
//relation
public function ordersCountRelation()
{
return $this->hasOne(Order::class)->selectRaw('user_id, count(*) as count')
->groupBy('user_id');
}
//attribute
public function getOrdersCountAttribute()
{
return $this->ordersCountRelation->count ?? 0;
}
//Then accessed like:
$user = User::with('ordersCountRelation')->find($id);
$user->ordersCount; //return only count
Any help will be highly appreciated
there is no need for using hasManyThrough.
just use some relations and withCount method:
$admin->posts->withCount('comments')->get();
then you can access it with: $comments_count

Resources