I have the following code:
$main = Main::with(['clients', 'events.orderitems' => function($query) {
$query->whereIn('order_id', function($query) {
$query->select('id')->from('orders')->where('orderPaid', 1)->orWhere('orderStatus', 3);
});
}])->where('id', $id)->first();
foreach($main->events as $dates) {
$all_paid = 0;
$all_pending = 0;
foreach($dates->orderitems as $item) {
if($item->orderPaid == 1) {
$all_paid = $all_paid + $item->quantity;
}
}
$dates->orderscount = $all_paid;
foreach($dates->orderitems as $item) {
if($item->orderStatus == 3) {
$all_pending = $all_pending + $item->quantity;
}
}
$dates->pendingcount = $all_pending;
}
Is there maybe an MYSQL way to Count the PAID orders and the orders with orderStatus == 3 in the SQL? I think, how I am doing it, it's way to messy and not very good for the performance.
So a "Main" has n-events which have n-orderItems.
I need to get to a "Main" Event, all the Events with all PAID and orderStatus == 3 items. How can I do that?
UPDATE - SOLUTION:
foreach($main->events as $dates) {
$dates->orderscount = OrderItems::where('events_id',$dates->id)->whereHas('orders', function($q) {
$q->where('orderPaid', 1);
})->sum('quantity');
$dates->pendingcount = OrderItems::where('events_id',$dates->id)->whereHas('orders', function($q) {
$q->where('orderStatus', 3);
})->sum('quantity');
}
Laravel has an aggregate method which does just that.
The same way you are using first to only get the first result of a query as in:
)->where('id', $id)->first();
to get the count you could use count()
DB::table('orders')->where('orderPaid', 1)->orWhere('orderStatus', 3)->count();
If you need the sum() of the products and not the count as in your title, you could for your particular example use:
$total_quantity = DB::table('orders')->where('orderPaid', 1)->orWhere('orderStatus', 3)->sum('quantity');
UPDATE:
As in your example to get both counts you would change you foreach to be something similar to:
foreach($main->events as $dates) {
$all_paid = DB::table('orders')->where('order_id',$dates->id)->where('orderPaid', 1)->count();
$all_pending = DB::table('orders')->where('order_id',$dates->id)->where('orderStatus', 3)->count();
$dates->orderscount = $all_paid;
$dates->pendingcount = $all_pending;
}
You can use sum() with your eloquent query in laravel. Check under the #Aggregates section here:
http://laravel.com/docs/4.2/queries
Related
I have a google task which gets all companies from my firebase database. I then go through each of those companies in a loop and call additional task for updating each specific company. My problem is that my companies count is increasing and when doing foreach like this i can get into memory limit issues. Here is the actual code for calling the tasks and subtasks:
$router->get('companies', function () use ($router) {
$slackDataHelpersService = new \App\Services\SlackDataHelpersService();
$companiesDocuments = $slackDataHelpersService->getCompanies();
foreach ($companiesDocuments->documents() as $document) {
$cid = $document->id();
createTask('companies', 'updateCompany', "{$cid}");
}
return res(200, 'Task done');
});
How can i separate my initial companies documents into chunks and call a task for each of those chunks? For example, a task that will go through every 100 documents instead of the whole list?
Here is what i tried without success(i used members in this case):
$router->get('test2', function () use ($router) {
$db = app('firebase.firestore')->database();
$membersRef = $db->collection('companies')->document('slack-T01L7H2NDPB')->collection('members');
$query = $membersRef->orderBy('created', 'desc')->limit(10);
$perPage = 10;
$batchCount = 10;
$lastCreated = null;
while ($batchCount == $perPage) {
$loopQuery = clone $query;
if ($lastCreated != null) {
$loopQuery->startAfter($lastCreated);
}
$docs = $loopQuery->documents();
$docsRows = $docs->rows();
$batchCount = count($docsRows);
if ($batchCount > 1) {
$lastCreated = $docsRows[$batchCount - 1];
}
echo $lastCreated['created'];
//createTasksByDocs($docs);
}
//return res(200, 'Task done');
});
I ended up making a function which uses a while loop and loops until it reaches the limit:
function paginateCollections($ref, $limit, $functionName)
{
$query = $ref->orderBy('created', 'desc')->limit($limit);
$perPage = $limit;
$batchCount = $limit;
$lastCreated = null;
while ($batchCount == $perPage) {
$loopQuery = clone $query;
if ($lastCreated != null) {
$loopQuery = $loopQuery->startAfter([$lastCreated]);
}
$docs = $loopQuery->documents();
$docsRows = $docs->rows();
$batchCount = count($docsRows);
if ($batchCount > 1) {
$lastCreated = $docsRows[$batchCount - 1]['created'];
}
if (function_exists($functionName)) {
$functionName($docs);
}
}
}
I'm trying to create a pagination in my search result. I have one queries in my repository like:
public function getFilteredVehicles($id,$pax,$categories,$search_type,$from_date,$to_date)
{
$vehicles = Vehicle::whereHas('destinations', function($q) use($id){
$q->where('destination_id',$id)
->where('active',1);
})
->paginate(1);
if($search_type == 'disposal' || $search_type == 'pnd')
{
$vehicles = $vehicles->where('registered_location',$id);
}
if($categories)
{
$vehicles = $vehicles->where('vehicle_categoryid',$categories);
}
return $vehicles;
}
The returned result again needs to be processed via loop like:
public function calculateLocationAmount($vehicles,$fdate,$tdate,$destination_id)
{
$datetime1 = new DateTime($fdate);
$datetime2 = new DateTime($tdate);
$interval = $datetime1->diff($datetime2);
$days = $interval->format('%a');
$days = $days+1;
$nights = $days-1;
foreach ($vehicles as $key => $vehicle) {
# code...
$perday_rate = $vehicle->destinations->where('id',$destination_id)->first()->pivot->day_rate;
$pernight_rate = $vehicle->destinations->where('id',$destination_id)->first()->pivot->night_rate;
$day_rate = $perday_rate * $days;
$night_rate = $pernight_rate * $nights;
$total_amount = $day_rate + $night_rate;
$vehicle['total_amount'] = $total_amount;
$vehicle['availability'] = 'true';
if($vehicle->whereHas('unavailability', function($q) use($fdate,$tdate){
$q->whereRaw("? BETWEEN `from_date` AND `to_date`", [$fdate])
->orwhereRaw("? BETWEEN `from_date` AND `to_date`", [$tdate]);
})->count()>0){
$vehicle['availability'] = 'false';
}
}
return $vehicles;
}
This final result needs to be paginated. How can i do it?
Using foreach is changing the value to collection due to which links is not working. If i don't do paginate() or get(), for loop is not executed.
Kindly help.
You can paginate your initial query just as you have, then loop over the pagination object as if it was your regular collection or use $pagination->items()
You should also use nested with('relation') in your initial query to stop N+1 queries https://laravel.com/docs/8.x/eloquent-relationships#constraining-eager-loads
my first query that gets all rows that contain both the user who requested friendship ( authenticated user id ) and inbound friendship ( inbound user id ). This works if I echo $rowsget, it echos the correct rows, the problem I'm having is that it will only loop through up to two usernames, once I take away the ability for it to loop through the profiles own username it will only loop through one row then stop, I have tried what some people have said to do but it now says this error message when I try to load the profile page, "Object of class Illuminate\Support\Collection could not be converted to int" Here is the code, any help is appreciated, I have been stuck on this for hours now.
Query
$rowsget = DB::table('friends')->where(function(Builder $query) use($uid) {
$query->where('requesteeid', $uid)
->orWhere('inboundid', $uid);
})
->where('approved', true)
->get();
$rowfetchfriend = [];
if(count($rowsget) > 0){
foreach($rowsget as $get) {
$getrequestee = $get->requesteeid;
$getinbound = $get->inboundid;
$rowfetchfriend += DB::table('users')->where('id', $getrequestee)-
>orWhere('id', $getinbound)->get(['id', 'avatar', 'username']);
}
Loop through usernames
foreach($rowfetchfriend as $loop) {
if($loop->id != $uid) { //make sure own user isnt displayed
echo $loop->username; // echo all usernames that are
}
}
}
Use this method (or the push() method) when adding to an array:
Instead of this:
$rowfetchfriend += DB::table('users')->where('id', $getrequestee)->orWhere('id', $getinbound)->get(['id', 'avatar', 'username']);
Try this:
$rowfetchfriend[] = DB::table('users')->where('id', $getrequestee)->get(['id', 'avatar', 'username']);
$rowfetchfriend[] = DB::table('users')->where('id', $getinbound)->get(['id', 'avatar', 'username']);
The class and its methods are listed here:
https://laravel.com/api/5.5/Illuminate/Support/Collection.html#method_count
You can use "push" method of laravel collection.
try this :
$rowfetchfriend = [];
if(count($rowsget) > 0) {
foreach($rowsget as $get) {
$getrequestee = $get->requesteeid;
$getinbound = $get->inboundid;
$temp = DB::table('users')->where('id', $getrequestee)->orWhere('id', $getinbound)->get(['id', 'avatar', 'username']);
array_push($rowfetchfriend, $temp->toArray());
}
}
and Loop through usernames :
for ($i=0; $i < count($rowfetchfriend); $i++) {
if($rowfetchfriend[$i][0]->id != $uid) { //make sure own user isnt displayed
echo $rowfetchfriend[$i][0]->username; // echo all usernames that are
}
}
I tested it and work correctly.
In a Laravel app, I'm trying to implement a structure where posts are fetched that have one or more of the tags that the user has access to. I wrote the code below to do that:
$query = new Posts();
if (count(Auth::user()->tags) > 0) {
$query = $query->whereHas('tags', function ($q) {
$i = 0;
foreach (Auth::user()->tags as $tag) {
if ($i == 0) {
$q->where('title', '=', $tag->title);
} else {
$q->orWhere('title', '=', $tag->title);
}
$i++;
}
});
}
$posts = $query->where('isTemplate', true)->orderBy($key, $order)->paginate(15);
This works, but feels off. So I'm wondering if there's a better way to do this?
#user4992124, Will this help you.
$query = Posts::query()
->where('isTemplate', true)
->orderBy($key, $order);
if (Auth::user()->tags->isNotEmpty()) {
$tags = Auth::user()
->tags
->pluck('title')
->toArray();
$query = $query->whereIn('tags', $tags);
}
$posts = $query->paginate(15);
I have a method that can receive a parameter of "month" and another of "year", you can receive both or only one of them.
In the case of only receiving the month I want to make a query that I look for in a field that is called "created_at" just looking for the month of that field date
At the moment I use this code but when doing a like it does not do it correctly
else if ($request->has('month')) {
$month = $request->input('month');
$currentTimestamp = date_create_from_format('n', $month)->getTimestamp();
$currentDate = date('m', $currentTimestamp);
$filters['updated_at'] = $currentDate;
unset($filters['month']);
}
$cars = Car::where(function($query) use($filters) {
foreach ($filters as $column => $value) {
if ($column === 'updated_at') {
$query->where($column, 'LIKE', '%'.$value.'%');
continue;
}
$query->where($column, 'LIKE', '%'.$value.'%');
}
})->orderBy('updated_at', 'desc')->get();
You should try this:
if ($request->has('month')) {
$month = $request->input('month');
Car::whereRaw('MONTH(created_at) = '.$month)->get();
}
You can use whereMonth method, like this:
$cars = Car::whereMonth('created_at', '12')->get();
Example with determining if a month value is exist:
if ($request->has('month')) {
$cars = Car::whereMonth('created_at', $request->input('month'))->get();
}
You can use laravel queryBuilder .
The idea is pretty simple. Build your query and execute it only when needed
carQuery = Car::newQuery();
if ($request->has('month') {
carQuery->where('created_at' .. do camparison you want);
}
if ( $request->has('year') {
// add extra query filter
}
cars = carQuery->get();