sum data from multiple relation in multiple relation in laravel - php

I have a User model, who hasMany categories and category hasMany posts and post hasOne Product
Now I want to sum all of the product->price of Auth::user()
how can i do that withSum or withCount function. in Laravel

Since your question doesnt present any details, I will assume that you have all the relations well set up.
You can get the sum using the relations like this
$sum = Product::query()
->whereHas('post', function($post) {
$post->whereHas('category', function($category) {
$category->whereHas('user', function($user) {
$user->where('id',auth()->id());
});
});
})
->sum('price');

Related

How to check relation data of a collection before sending it to view

I have a Controller method like this:
public function awaiting()
{
$producers = Producer::where('producer_process',4)->get();
$producers_list = [];
foreach($producers as $producer){
if($producer->brand->brand_rejected == 0){
array_push($producers_list, $producer);
}
}
return view('admin.brands.awaiting', compact('producers_list'));
}
So basically there's One To One relationship between Producer model & Brand model.
In order to get the collection of brands table records that has producer_process of 4 and ALSO the brand_rejected field of related brands table record must be set to 0, I added an array_push and check the condition.
Now this works fine and properly shows the correct data but I wanted to know, what is the shorthand method of doing this with Eloquent relationships?
I mean is there any concise and useful method written in Eloquent relationships that can do this without using array_push or another foreach loop?
You can use whereHas to constrain the result set based on the existence of a relationship. Here we are saying we only want producers that have the field 'produce_process' set to 4 and have a brand with a field of 'brand_rejected' set to 0:
$producers = Producer::where('producer_process', 4)
->whereHas('brand', function ($q) { $q->where('brand_rejected', 0); })
->get();
If you want these producers to have their brand relationship loaded to use you should eager load that. Before the get call you can tell it to load the relationship:
$producers = Producer::where(...)->whereHas(...)->with('brand')->get();
Laravel 5.8 Docs - Eloquent - Relationships - Querying Relationship Existence whereHas
Laravel 5.8 Docs - Eloquent - Relationships - Eager Loading with
You can try this:
public function awaiting()
{
$producers = Producer::where('producer_process',4)
->with('brand', function($q) {
$q->where('brand_rejected', 0);
})->get();
// dd($producers);
dd($producers->pluck(brand));
Sure you can use the method with() also with the where() clause to can apply some conditions to the relationship
Example
$yourQuery->with('brand', function($query){
$query->where('brand_rejected', 0);
});
check this for more info
https://laravel.com/docs/9.x/eloquent-relationships#constraining-eager-loads
I hope it's helpful

Laravel eloquent how to get relationships relationship?

I have Users table,Jobs table and JobStatus table. I get user jobs using relationship
return User::find($dto->getUserId())
->jobs()
This will return all user jobs as collection, not as relationship inside user model.
Now I need to get jobs statuses, but when I try this
User::find($dto->getUserId())
->jobs()
->statuses()
I get error Call to undefined method. I need to get statuses as collection so I can use where,sort by etc while getting them from db. Is there any way to do so?
I need to do something like this , but with statuses
return User::find($dto->getUserId())
->jobs()
->has('status')
->where('role','responsible')
->where('jobs.created_at','>=',Carbon::now()->subDays($dto->getPeriod())->toDateString())
->get();
To retrieve the jobs by filtering on the statuses relationship, you can do it like this:
$user->jobs()->whereHas('statuses', function ($query) {
// Perform filter on the query for jobs->statuses
})->get();
For more information about querying relationship existence: https://laravel.com/docs/7.x/eloquent-relationships#querying-relationship-existence
If you want to retrieve the statuses instances, you can do it like this:
$statuses = JobStatus::where('created_at', '>=', now())
->whereHas('jobs', function ($query) use ($user) {
$query->whereUserId($user->id);
})
->get();
Just use jobs without parenthesises to get the model itself :
User::find($dto->getUserId())
->jobs
->statuses;
define your statuses() function first with the relations in your model with the jobs
like many to many or one to many relationship
public function statuses(){
return $this->belongsToMany('App\Job')->withTimestamps();
}

Eager loading the first item from multiple value from a related table in laravel 5.4

I have two tables 'purchases' and 'accounts_purchase_history'. purchase has many accounts history. So I need to get all the purchases with the latest history.
What i have done so far
$purchases = Purchases::with(['accounts_purchase_historie' => function($query){
return $query->orderBy('id','DESC')->first();
}])->orderBy('id','DESC')->where('status','extended')->get();
But this query only gets the first purchase history, How can i solve this?
You can use a HasOne relationship:
public function latest_history() {
return $this->hasOne(...)->orderBy('id','DESC');
}
$purchases = Purchases::with('latest_history')
->orderBy('id','DESC')
->where('status','extended')
->get();
foreach($purchases as $purchase) {
$purchase->latest_history
}
However, this will still fetch all the histories from the database in the background.

Trouble with hasManyThrough in Laravel

Maybe dublicate, but my search hasn't any success. What we have:
Laravel 5.2, three tables
user_tariff_hours_history
id
user_tariff_id
...
user_tariff
id
user_id
...
users
id
...
I want to get user through user_tariff for current user_tariff_hours_history
As official Laravel Docs said I need to have getter with the hasManyThrough method in my user_tariff_hours_history's model https://laravel.com/docs/5.5/eloquent-relationships#has-many-through
But result of the query with that getter didn't expected.
I get whole users table, not a user for current user_tariff_hours_history
getter:
public function getUsers() {
return $this->hasManyThrough('App\SARegistration',
'App\SAUser_tariff',
'user_id', //FK on SARegistration (users)
'id', //Local Key of ?
'user_tariff_id'); //FK on SAUser_tariff (user_tariffs)
}
Note: in docs there are 6 params for the hasManyThrough, but Laravel said it has only 5 params, than I was trying to use diffirent combo of params
Define hasManyThrough relationship called userTariffHoursHistory in User model and use whereHas():
User::whereHas('userTariffHoursHistory', function($q) use($userTariffHoursHistoryId) {
$q->where('id', $userTariffHoursHistoryId);
})->first();
Or define two hasMany() relationships (userTariffs in User model and userTariffHoursHistory in UserTariff model) and then use nested whereHas():
User::whereHas('userTariffs', function($q) use($userTariffHoursHistoryId) {
$q->whereHas('userTariffHoursHistory', function($q) use($userTariffHoursHistoryId) {
$q->where('id', $userTariffHoursHistoryId);
});
})->first();

Laravel Eloquent Retrieving only certain rows basing on relation field

I have a number of models and I have the relationships set up correctly I believe.
I want to retrieve all of the models from a table if and only if the active column of a foreign key table is true.
I have tried a number of variations but to no avail.
Below is the set up.
The table is question is called device, which points to a table called dep.
The DEVICE model has the following relationship to DEP
public function dep() {
return $this->belongsTo('App\Dep');
}
The DEP model has a column called active, which is set to true or false.
What eloquent command should I use to return all Devices where the active field of the DEP table is true?
At the moment I am having to get all the DEP models and then only get the devices if the active field is set to true but I am sure there must be a more elegant approach.
Thanks.
If you want to limit the results based on the existence of a field in a related model, you want to take a look at the whereHas method.
$devices = Device::whereHas('dep', function($query) {
$query->where('active', '=', true); // Replace true with 1 if you aren't using casts
})->get();
This will get all devices that have a dep with the active field of true. This will not fetch dep along with the Device though. If you want that, then just use whereHas with eager loading as you normally would do like this:
$devices = Device::with('dep')->whereHas('dep', function($query) {
$query->where('active', '=', true);
})->get();
You can simply add a filter to your relationship:
public function dep() {
return $this->belongsTo('App\Dep')->where('active', true);
}
Or, if you prefer to keep the dep relation unaltered, you can consider to add another relation to retrieve only the active models:
public function depActive() {
return $this->belongsTo('App\Dep')->where('active', true);
}
This will return all the DEP models related to a Device, having active = 1.
You can use the relation as follow:
$depActives = $device->depActive;
or
$depActives = $device->depActive()->get();
boh of them will do the same

Categories