Laravel Eloquent - How Can I Sum fields inside relation's column? - php

I need to sum every paid_amount inside of each expense_payment_liab instead of returning all these
individual paid_amount as it can be seen in images for clear view.So far my query looks like this:
Model Relation is like Voucher has many Expenses and Expenses has many Expensepaymentliab.
This is so far what I tried:
$expense = Voucher::where('voucher_date', $request->date)
->where('account_id', 1)
->with(['expenses' => function ($expense) use ($date) {
$expense->with(['expPaymentLiab' => function ($inner) use ($date) {
return $inner->select('paid_amount', 'expense_id')->where('paid_date', '=', $date);
//need to return the sum of paid_amount.
// I've also tried this
//$inner->sum('paid_amount')
// $inner->sum('paid_amount', 'expense_id')
}]);
$expense->select('id', 'date', 'total_amount', 'voucher_id');
}])->get();
These are the images please check
Need to sum such paid_amount field.

You can use withCount to sum the paid_amount field.
Voucher::where('voucher_date', $request->date)
->where('account_id', 1)
->with(['expenses' => function ($expense) use ($date) {
// select the columns first, so the subquery column can be added later.
$expense->select('id', 'date', 'total_amount', 'voucher_id');
$expense->withCount(['expPaymentLiab AS paid_sum' => function ($query) use ($date) {
return $query->select(DB::raw('SUM(paid_amount)'))->where('paid_date', '=', $date);
}]);
}])
->get();

Related

Eloquent: has() condition against database value

I have a simple relationship between Bottles and InventoryItems:
InventoryItem.php:
public function bottles(): HasMany
{
return $this->hasMany(InventoryItemBottle::class);
}
I'm trying to query for InventoryItem's that have a bottles count of greater then a user entered threshold.
The user's input is saved in a JSONB. Part of the query looks like this and I've commented the problem line:
->when(
$filters['filter'] === 'show_above_max_threshold',
fn (Builder $query): Builder => $query->where(function (Builder $query): Builder {
return $query->whereColumn('info->quantity', '>', 'info->high_level_warning');
})
->orWhere(function (Builder $query): Builder {
return $query->has('bottles', '>', 'info->high_level_warning'); // stuck here
})
)
The has() method should help here, but how do I get the high_level_warning from the database to pass to it? Or is there another method I could use?
You can use the has function.
See if this helps you.
$threshold = 2;
$items = InventoryItem::has('bottles', '>=', $threshold)->get();

laravel filter only nested condition

I want to filter ONLY nested values in dealTransactions.
In plain English, Merchant wants only dealTransactions have provided dates with Deals.
I tried something like below but it does not work.
dates = ['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04', '2019-01-05'];
$merchant = Merchant::with(['deals.dealTransactions'])->where('slug', $slug)
->whereHas('deals.dealTransactions', function($query) use ($dates) {
foreach($dates as $date) {
$query->where('date', '=', $date);
}
})
->first();
deal_transactions table
id, deal_id, date
deals table
id, merchant_id,
merchants table
id, many columns for merchant
Thank you
You should be able to do this with a eager load constraint on the nested relationship:
$merchant = Merchant::where('slug', $slug)
->with(['deals.dealTransactions' => function ($query) use ($dates) {
$query->whereIn('date', $dates);
}])->first();
If I understood correctly your schema, this might help:
// Here you define the scope that will be used to select & eager load.
$transactionsScope = function ($q) use ($dates) {
return $q->whereIn('date', $dates);
};
// All merchant of slug in/with that transaction's scope.
$merchant = Merchant::where('slug', $slug)
->whereHas('deals', function ($q) use ($transactionsScope) {
return $q->whereHas('dealTransactions', $transactionsScope);
})
->with(['deals' => function ($q) use ($transactionsScope) {
return $q->with('dealTransactions', $transactionsScope);
}])
->firstOrFail();

Laravel withCount use function in model

I have model Post:
protected $guarded = [];
public function reviews() {
return $this->hasMany(Review::class);
}
My reviews table have a column type with values: 1(good),2(comment),3(negative).
I need get count reviews for every type. I need globally get these counts. I know that I can do in model something like this:
protected $withCount = ['reviews'];
But this get me all reviews. But I need get count only for every type.
You could use the withCount method and do sub queries inside:
$counts = Post::withCount([
'reviews',
'reviews as good_reviews' => function ($query) {
$query->where('type', 1);
}],
'reviews as bad_reviews' => function ($query) {
$query->where('type', 3);
}],
}])->get();
You can access the count like this:
echo $counts[0]->good_reviews;
For more info: Docs
you can use GroupBy method for it.
Something like this:
DB::table('reviews')
->select('type', DB::raw('count(*) as total'))
->groupBy('type')
->get();

OrderBY On model relationship eloquant on controller?

I am not able to find any perfect solution for it.
Controller:
$servicerequest = ServiceRequest::selectRaw('count(id) as totalservice,max(created_date) as last_service,service_provider_id,id,service_id,account_id,service_request,created_date')->with(['account' => function($first) use ($keyword) {
$first->select('id', 'restaurant_name')->orderBy('restaurant_name', 'DESC');
}])
->with(['serviceProvider' => function($query) use ($keyword) {
$query->select('id', 'company_name');
}])->groupBy('account_id')
->orderBy('company_name', 'DESC')
->paginate(100);
I need an order by on model relation table field and that effect on main table data. because it's and one to one relationship so no need to order by on the inside.
Like I need to the orderby whole on relations data.
Collection:
You must make join your relation table to used orderBy relation table.
You can try this code.
$servicerequest = ServiceRequest::selectRaw('count(id) as totalservice, max(created_date) as last_service,service_provider_id,id,service_id,account_id,service_request,created_date, SERVICEPROVIDERTABLE.company_name')
->join('serviceProvider', 'SERVICEPROVIDERTABLE.id', '=', 'SERVICEREQUESTTABLE.service_provider_id')
->with([
'account' => function ($first) use ($keyword) {
$first->select('id', 'restaurant_name')
->orderBy('restaurant_name', 'DESC');
}
])
//->with([
// 'serviceProvider' => function ($query) use ($keyword) {
// $query->select('id', 'company_name');
// }
//])
->groupBy('account_id')
->orderBy('SERVICEPROVIDERTABLE.company_name', 'DESC')
->paginate(100);
i hope this works.

Laravel filter with query builder retrieving wrong data

The query is retrieving wrong data, must retrieve only departamento not null. Can anyone help me?
Code:
$banca = Banca::with(['trabalho.membrobanca.departamento' => function($query) use ($d) {
$query->where('id', $d);
}])->get();
$banca = collect($banca)
->unique('trabalho_id')
->values()
->all();
The diagram with relationship.
You can put the filter on the memrobanca table and filter on null values.
$banca = Banca::with([
'trabalho.membrobanca' => function($query) use ($d) {
$query->where('departamento_id', $d)
->whereNotNull('departamento_id')
->with('departamento');
}
])
->get();
You can use Laravel has() function. It will return return Banca where departamento is not null
$banca = Banca::with(['trabalho.membrobanca.departamento' => function($query) use ($d) {
$query->where('id', $d);
}])
// has function will return banca if banca has non-null departamento
->has('trabalho.membrobanca.departamento')
->get();
Check this:
https://laravel.com/docs/5.4/eloquent-relationships#querying-relationship-existence

Categories