Laravel sum from relationship with condition - php

I have the following query where I have a conditional query with relation between two models. I need sum of column hours from the attendance where the conditions are met. I have tried the following, but it's not working.
$users = User::with('attendance')
->whereHas('attendance', function (Builder $query) use ($end, $start) {
$query->whereBetween('date', [$start, $end])
->where('status', 2)
->select(DB::raw('SUM(hours) as h'));
})->orderBy('name')
->where('status', 0)
->get();
In my blade
#foreach($users as $user)
{{ $user->h }}
#endforeach
Please help

User::whereHas('attendance')
->withSum(['attendance' => function ($query) use ($start, $end){
$query->whereBetween('date', [$start, $end])
->where('status', 2);
}], 'hours')
->get();
you can access sum hours using attendance_sum_hours property
({relation}_{function}_{column})
$user->attendance_sum_hours
Tip:
one more thing; $query->whereBetween('date', [$start, $end]) be carefull when using whereBetween on datetime column because will compare also the time, so the results won't be favorable
use whereBetweenColumn('date(date)', [$start, $end])

I do not think you can do this with whereHas, but this is how you would do it using joins. This would return all users that have an attendance between 2 dates and then give you the count.
$users = User::with('attendances')
->selectRaw('users.*, SUM(attendances.hours) as hours_sum')
->leftJoin('attendances', 'users.id', 'attendances.user_id')
->whereBetween('attendances.date', [$startDate, $endDate])
->groupBy('users.id')
->get();
However, if you want to return all users but if they have no attendance it will return 0 you can do the following
$users = User::with('attendances')
->selectRaw('users.*, COALESCE(SUM(attendances.hours), 0) as hours_sum')
->leftJoin('attendances', function (JoinClause $joinClause) {
$joinClause->on('users.id', 'attendances.user_id')
->whereBetween('attendances.date', [$startDate, $endDate]);
})
->groupBy('users.id')
->get();

Related

OrderBy its not wokring on laravel

i have a problem when doing "orderBy" name product. here are my codes
$resume = Transaction::with(['product' => function ($q) {
$q->orderBy('name_product','ASC');
}])
->where('status', 'keluar')
->where('status', 'masuk')
->get();
but my code its not working... here is the output
result
Use the collection to sort instead. It allows for sorting based on a nested property.
$resume = Transaction::with('product')
->where('status', 'keluar')
->where('status', 'masuk')
->get()
->sortBy('product.name_product')
->values();
Because you are applying condition to product, not in transaction.
I have another suggestion use whereHas.
Transaction::whereHas('product', function($query) {
$query->->orderBy('name_product','ASC');
})->where('status', 'keluar')
->where('status', 'masuk')
->get();

Laravel Query Sending Different Result For Same Problem

Hi I am trying to create a one on one messaging system on LARAVEL. It was working all fine until for some users it started showing different result then expected. And it happens only for some users.. What is wrong with this query
$id =$receiver->id;
$messages = Message::where(function ($query) use ($id) {
$query->where('user_id', '=', Auth::user()->id)
->where('receiver_id', '=', $id);
})->orWhere(function ($query) use ($id) {
$query->where('user_id', '=', $id)
->where('receiver_id', '=', Auth::user()->id);
})->get();
After I return $messages the result is like this...
Working Result: Messages are coming sequentially..
In View It shows like this..
Same Query Bad Result
In the view you can see date are not aligned in order
I really can't figure out what went wrong if you can help I would really appreciate..
Your date is casting as UTC with ISO-8601 format, but I think date is not related with your issue, if you are not ordering with timestamp.
I suggest you to use orderBy with id, it can solve your issue easily :
$messages = Message::where(function ($query) use ($id) {
$query->where('user_id', '=', Auth::user()->id)
->where('receiver_id', '=', $id);
})->orWhere(function ($query) use ($id) {
$query->where('user_id', '=', $id)
->where('receiver_id', '=', Auth::user()->id);
})
->orderBy('id', 'ASC')
->get();

Laravel Collection Query, Where I am going wrong?

My tables looks like this
area_trip
|id|dispatch_id|trip_id|status|
equipment_trip
|equipment_id|trips_id|dispatch_id|
trips
|id|dispatch_id|status
I am trying to pass collection to my resource. Can someone check my query and tell me what I am doing wrong as following query returning all the data matches dispatch_id whether it matches equipment_id or not. Btw I am new to laravel.
return
Resources::collection(
area_trip::where('dispatch_id', $request->dispatch_id)
->where('status', 1)
->orWhere('status', 9)
->whereHas('equipment_trip', function($query) use ($request) {
$query->where('equipment_trip.equipment_id', '=', $request->equipment_id);
})
->with(['equipment_trip', 'createdBy', 'updatedBy', 'area', 'trips'])
->orderBy('tripStartDate', 'ASC')
->orderBy('status', 'ASC')
->get());
Here is the relationship set up in area_trip model
public function equipment_trip()
{
return $this->belongsTo(equipment_trip::class, 'trip_id', 'trips_id');
}
I believe your whereHas sub query is incorrect also instead of where and orWhere use where in and you can define all statuses necessary, try this:
Resource::collection(area_trip::where('dispatch_id', $request>dispatch_id)
->whereIn('status', [1, 9])
->whereHas('equipment_trip', function($query) use ($request) {
return $query->where('equipment_id', '=', $request->equipment_id);
})
->with(['equipment_trip', 'createdBy', 'updatedBy', 'area', 'trips'])
->orderBy('tripStartDate', 'ASC')
->orderBy('status', 'ASC')
->get());

How do you filter the user with hasRole() in Laravel 5 within relational query?

I want to filter my query and return only if the user hasRole "Premium" and limit the result to 10.
Along with this query is a count of records which Conversion has and sort it in DESC order by total column.
Right now I have a working query that returns the count of Conversion and with a User but without user filter Role.
// Model Conversion belongs to User
// $from & $end uses Carbon::createDate()
// Current code
$query = Conversion::select('user_id',DB::raw('COUNT(*) as total'))
->whereBetween('created_at', [$from,$end])
->where('type','code')
->where('action','generate')
->whereNotNull('parent_id')
->with('user')
->groupBy('user_id')
->orderBy('total', 'DESC')
->take(10)
->get();
// current result
foreach ($query as $q) {
$q->user->name; // To access user's name
$q->total; // To access total count
}
// I tried this but no luck
$query = Conversion::select('user_id',DB::raw('COUNT(*) as total'))
->whereBetween('created_at', [$from,$end])
->where('type','code')
->where('action','generate')
->whereNotNull('parent_id')
->with('user', function($q) {
$q->hasRole('Premium');
})
->groupBy('user_id')
->orderBy('total', 'DESC')
->take(10)
->get();
You need to use whereHas instead of with, like this:
->whereHas('user', function ($query) {
$query->where('role','Premium');
})
Use the whereHas() instead of with(). Also, you can't use hasRole() if it's not a local scope:
->whereHas('user.roles', function($q) {
$q->where('name', 'Premium');
})

laravel query: orWhere: double condition

I have the following query, which does not give me the expected result:
$query = $query->join('events_dates', function($join) use ($data){
$join->on('events.id', '=', 'events_dates.event_id')
->where('events_dates.start_date', "<=", date_format(date_create($data['date_end']), "Y-m-d"))
->where('events_dates.end_date', '>=', date_format(date_create($data['date_start']), "Y-m-d"))
->orWhere('recurrent', "=", 1)
->where((strtotime($data["date_start"]) - strtotime('event_dates.start_date')) % ('events_dates.repeat_interval' * 86400), '=', 0);
});
There are 4 where clauses in this query.
The requirement is that either the two first where clauses are executed, or either two last depending on the recurrentfield.
PHP returns an error division by zero, because the last Where clause should not be executed when recurrentis 0.
Any suggestions?
I don't know your exact goal nor do I know what your db looks so this is just a wild guess:
$query = $query->join('events_dates', function($join) use ($data){
$join->on('events.id', '=', 'events_dates.event_id')
->where('events_dates.start_date', "<=", date_format(date_create($data['date_end']), "Y-m-d"))
->where('events_dates.end_date', '>=', date_format(date_create($data['date_start']), "Y-m-d"))
->orWhere('recurrent', "=", 1)
->whereRaw('DATEDIFF(?, event_dates.start_date) % event_dates.repeat_interval = 0', array($data['date_start']));
Update
This might help for the between two dates part
->where('events_dates.start_date', '<=', new Carbon($data['date_end']))
->where('events_dates.end_date', '>=', new Carbon($data['date_start']))

Categories