Laravel Eloquent group by relation - php

I'm struggling to understand how to use Eloquent/Query Builder with relationships.
I have the following:
$plantLots = PlantLot::with('controlNumber')
->whereHas('controlNumber', function ($q) use ($fromDate, $toDate) {
$q->where('created_at', '>=', $fromDate);
if($toDate != '') {
$q->where('created_at', '=<', $toDate);
}
$q->groupBy('creator_id');
})->get();
I want to group by creator_id, but I still just get a single collection of data.
What am I doing wrong?

change it to
$plantLots = PlantLot::with(['controlNumber' => function($q){
$q->groupBy('creator_id');
}])
->whereHas('controlNumber', function ($q) use ($fromDate, $toDate) {
$q->where('created_at', '>=', $fromDate)
->when($toDate != '',function($q){
$q->where('created_at', '=<', $toDate);
});
})->get();
Hope it helps.

Related

laravel sum and group by in sub query

I have this query
$t_items_between = TransferItem::whereHas('transfer', function ($query) use($old_until_date, $inventory_id, $old_from_date_interval) {
$query->where('document_date', '>=', $old_from_date_interval);
$query->where('document_date', '<=', $old_until_date);
$query->where('to_inventory_id', $inventory_id);
})
->with(['transfer' => function($query) use($old_until_date, $inventory_id, $old_from_date_interval) {
$query->where('document_date', '>=', $old_from_date_interval);
$query->where('document_date', '<=', $old_until_date);
$query->where('to_inventory_id', $inventory_id);
}
])
->whereIn('item_id', $subset)
->addSelect(['quantity' => TransferItem::selectRaw('sum(quantity)')
->groupBy('item_stock_id')
->from((new TransferItem)->getTable() . ' as ti')
->whereColumn('ti.item_stock_id', (new TransferItem)->getTable() . '.item_stock_id')
])
->get();
So TransferItem is the model of the table transfer_items. transfer_items has 4 columns: id, transfer_id, item_stock_id and quantity.
What I am trying to do is to sum the quantity of each result, grouping by the item_stock_id, but the query above doesn't work. How would I approach it?
try using map
$t_items_between = TransferItem::whereHas('transfer', function ($query) use($old_until_date, $inventory_id, $old_from_date_interval) {
$query->where('document_date', '>=', $old_from_date_interval);
$query->where('document_date', '<=', $old_until_date); $query->where('to_inventory_id', $inventory_id);
})
->with(['transfer' => function($query) use($old_until_date, $inventory_id, $old_from_date_interval) {
$query->where('document_date', '>=', $old_from_date_interval);
$query->where('document_date', '<=', $old_until_date); $query->where('to_inventory_id', $inventory_id);
}
])
->whereIn('item_id', $subset)
->get()
->groupBy('item_stock_id')
->map(function ($q) {
return $q->sum('quantity');
});
Visit https://laravel.com/docs/9.x/collections

Using whereIn with orWhere functions in Eloquent query

I am struggling to add a whereIn to a more complex query:
$events = Toolplan::query()
->select('id', 'eventId', 'resourceId', 'title', 'start', 'end')
->where(function ($query) use ($start, $end) {
$query->whereDate('start', '>=', $start)->whereDate('end', '<=', $end);
})
->orWhere(function ($query) use ($start, $end) {
$query->whereDate('start', '<=', $start)->whereDate('end', '>=', $end);
})
->orWhere(function ($query) use ($start, $end) {
$query->whereDate('end', '>=', $start)->whereDate('end', '<=', $end);
})
->orWhere(function ($query) use ($start, $end) {
$query->whereDate('start', '>=', $start)->whereDate('start', '<=', $end);
})
// gives "General error: 1096 No tables used":
->whereIn('eventId', function ($query) use ($eventIds){
$query->whereIn('eventId', $eventIds);
})
// no effect:
// ->whereIn('eventId', $eventIds)
->get();
I tried to add it as a function and in simple form but the function leads to General error: 1096 No tables used and the other shows no effect at all, because the collection is far too large and should be only 4 items after whereIn and the orWhere selection. $eventIds is a flat array:
["P000018","P000054","P000021","P000030"]

Laravel query not working when using as scope

I'm trying to find records by time interval. In table there are columns like 'date_from' and 'date_to', those are specify starts and ends date of an event.
public function scopeByTimeInterval($query, $dateInterval)
{
$query->where(function ($query) use ($dateInterval) {
[$from, $to] = $dateInterval;
$query->where([
['date_from', '<=', $from],
['date_to', '>=', $to]
]);
$query->orWhere([
['date_from', '>=', $from],
['date_to', '<=', $to]
]);
$query->orWhereBetween('date_from', $dateInterval);
$query->orWhereBetween('date_to', $dateInterval);
});
}
when I use where query directly, there are no problem. I can see all events between those dates. But if I use it as a scope, it returns me every events in given year and month and not the interval..
What might cause kind of behavior ? Or am I missing something ?
As mentioned in the comments, your query is essentially selecting everything. If you're trying to get the events that are happening during the $from and $to dates you could do something like:
public function scopeDateInterval($query, $interval)
{
[$from, $to] = $interval;
$query
->where(function ($query) use ($from, $to) {
$query
->where(function ($query) use ($from) {
$query
->where('date_from', '<=', $from)
->where('date_to', '>=', $from);
})
->orWhere(function ($query) use ($to) {
$query
->where('date_from', '<=', $to)
->where('date_to', '>=', $to);
})
->orWhere(function ($query) use ($from, $to) {
$query
->where('date_from', '>=', $from)
->where('date_to', '<=', $to);
});
});
}
The above is basically saying where the $from or $to is between the start and end dates, or the start and end dates are between the $from and $to.
Think you miss return $query->where...

check condition within query in laravel

$q = Order::select(
'orders.*',
'items.date_start',
'items.date_end',
'items.location_name',
'items.category_id'
)
->join('items', 'items.item_id', '=', 'orders.item_id')
->leftJoin('orders_items', function ($join) use ($user_id)
{
$join->on('orders_items.order_id', '=', 'orders.order_id')
->on('orders_items.item_id', '=', 'orders.item_id')
->where('orders_items.user_id', '=', $user_id);
})
->with('Items')
->where(function ($query) use ($select_balance) { // This is where event is in the future, or it has a balance and is not draft.
$query->where('items.date_end', '>=', Carbon\Carbon::now()->toDateString())
->orWhere(function ($query) use ($select_balance) {
$query->where(DB::raw($select_balance), '>', 0)
->whereNotIn('orders.status', [0, 79]);
});
});
i would like to set a condition if (date_start == date_end) then
$query->where('items.date_end', '>=', Carbon\Carbon::now()->toDateString())
->orWhere(function ($query) use ($select_balance) {
$query->where(DB::raw($select_balance), '>', 0)
->whereNotIn('orders.status', [0, 79]);
});
else
$query->where('items.date_end', '>', Carbon\Carbon::now()->toDateString())
->orWhere(function ($query) use ($select_balance) {
$query->where(DB::raw($select_balance), '>', 0)
->whereNotIn('orders.status', [0, 79]);
});
how to set a condition within query i try to end query after ->with(items) but that say $q-> has syntax error please guide and explain how to over come this issue
You can use conditional clauses: https://laravel.com/docs/5.5/queries#conditional-clauses
Animals::when($condition, function($query) {
$query->where('size', 'big');
})->when(!$condition, function($query)) {
$query->where('size', 'small');
})->get();
In the example, if $condition is true then we fetch big animals, otherwise we fetch small animals.

Laravel Query Filter different Tables with AND

I have a problem with my Larvel Query it doesn't work as desired.
It should Filter "Campaigns" with the attributes Teams, Channels, Region and Timeperiod with Start and Enddate. The Timeperiod is no problem.
The user can Filter for differen Teams/Channels/Region and can choose no, one or more Attribute, which should connect as or.
The desired Result should give all Campaign which has the selected Teams AND Channels AND Region. But at the moment I get every Campaign which has the selected Teams OR the selected Channels OR the selected Region.
public function searchCampaigns($page, $limit, $data)
{
$startDate = $data['startDate'];
$endDate = $data['endDate'];
$campaigns = Campaign::distinct()->select('campaigns.*')
->join('campaign_team', 'campaign_team.campaign_id', '=', 'campaigns.id')
->join('campaign_region', 'campaign_region.campaign_id', '=', 'campaigns.id')
->join('campaign_channel', 'campaign_channel.campaign_id', '=', 'campaigns.id')
->join('teams', 'campaign_team.team_id', '=', 'teams.id')
->join('regions', 'campaign_region.region_id', '=', 'regions.id')
->join('channels', 'campaign_channel.channel_id', '=', 'channels.id')
//Interesting Part
->whereIn('teams.id', $data['teams'])
->whereIn('regions.id', $data['regions'])
->whereIn('channels.id', $data['channels'])
->where(function ($query) use ($startDate, $endDate) {
$query->where('campaigns.start_date', '>=', $startDate)
->where('campaigns.end_date', '<=', $endDate);
})
->orWhere(function ($query) use ($startDate, $endDate) {
$query->where('campaigns.end_date', '<=', $endDate)
->where('campaigns.end_date', '>=', $startDate);
})
->orWhere(function ($query) use ($startDate, $endDate) {
$query->where('campaigns.start_date', '>=', $startDate)
->where('campaigns.start_date', '<=', $endDate);
})
->orWhere(function ($query) use ($startDate, $endDate) {
$query->where('campaigns.start_date', '<=', $startDate)
->Where('campaigns.end_date', '>=', $endDate);
}) ->orderBy('start_date', 'asc');
$result['count'] = sizeof($campaigns->lists('id'));
$result['campaigns'] = $campaigns->skip($limit * ($page - 1))->take($limit)->get();
return $result;
}
Try this one. It shall work. Let me know if any issues happen :)
public function searchCampaigns($page, $limit, $data)
{
$result = [];
// Checking Validity of Start Date
if (empty($data['startDate']) || (Carbon::createFromFormat('Y-m-d', $data['startDate']) === false))
return $result;
// Checking Validity of End Date
if (empty($data['endDate']) || (Carbon::createFromFormat('Y-m-d', $data['endDate']) === false))
return $result;
// Comparing Start & End Date
$startDate = Carbon::parse($data['startDate']);
$endDate = Carbon::parse($data['endDate']);
if($startDate->gt($endDate))
return $result;
if($endDate->lt($startDate))
return $result;
$startDate = $data['startDate'];
$endDate = $data['endDate'];
$campaigns = Campaign::distinct()->select('campaigns.*')
->join('campaign_team', 'campaign_team.campaign_id', '=', 'campaigns.id')
->join('campaign_region', 'campaign_region.campaign_id', '=', 'campaigns.id')
->join('campaign_channel', 'campaign_channel.campaign_id', '=', 'campaigns.id')
->join('teams', 'campaign_team.team_id', '=', 'teams.id')
->join('regions', 'campaign_region.region_id', '=', 'regions.id')
->join('channels', 'campaign_channel.channel_id', '=', 'channels.id')
->whereIn('teams.id', $data['teams'])
->whereIn('regions.id', $data['regions'])
->whereIn('channels.id', $data['channels'])
->where('campaigns.start_date', '>=', $startDate)
->where('campaigns.end_date', '<=', $endDate);
->orderBy('start_date', 'asc');
$result['count'] = sizeof($campaigns->lists('id'));
$result['campaigns'] = $campaigns->skip($limit * ($page - 1))->take($limit)->get();
return $result;
}

Categories