This is my job.
When I run this job the online invoices query doesn’t display anything, but what is intriguing is that when I swap the places of the $onlineInvoices and the $offlineInvoices variables the $onlineInvoices query works while the $offlineInvoices doesn’t.
It worked fine when I redefined the $monthlyInvoices again below the $offline_sales variable, But I would like to know why this occurs.
<?php
namespace AppJobs;
use AppModelsInvoice;
use AppModelsInvoiceMonthlyStatistics;
use CarbonCarbon;
use CarbonCarbonPeriod;
use IlluminateBusQueueable;
use IlluminateContractsQueueShouldBeUnique;
use IlluminateContractsQueueShouldQueue;
use IlluminateDatabaseEloquentModel;
use IlluminateFoundationBusDispatchable;
use IlluminateQueueInteractsWithQueue;
use IlluminateQueueSerializesModels;
class InvoiceMonthlyStatisticsJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$period = CarbonPeriod::create('2021-08-18', '1 month', Carbon::now()->toDateString());
foreach ($period as $date) {
$monthlyInvoices = Invoice::
whereRaw('YEAR(created_at) = ?', $date->format('Y'))
->whereRaw('MONTH(created_at) = ?', $date->format('m'));
$total_sales = $monthlyInvoices
->sum('net_price');
$offline_sales = $monthlyInvoices
->where('type', '=', 'offline')
->sum('net_price');
$online_sales = $monthlyInvoices
->where('type', '=', 'online')
->sum('net_price');
$invoiceStats = (new InvoiceMonthlyStatistics)->create([
'total_sales' => $total_sales,
'online_sales' => $online_sales,
'offline_sales' => $offline_sales,
'month' => $date->format('m'),
'year' => $date->format('y')
]);
}
$invoiceStats->save();
}
}
Advertisement
Answer
This is because $monthlyInvoices is a query builder.
When you add a where statement, it remains even after you called sum:
$offline_sales = $monthlyInvoices
->where('type', '=', 'offline') //here
->sum('net_price');
That’s the problem, because when you do:
$online_sales = $monthlyInvoices
->where('type', '=', 'online')
->sum('net_price');
->where('type', '=', 'offline') is still here, because you previously added it.
In a sense, your second query is the same as doing:
$online_sales = $monthlyInvoices
->where('type', '=', 'offline')
->where('type', '=', 'online')
->sum('net_price');
Now you probably see the problem here. One quick way to solve this is to clone the query builder before each query.
$offline_sales = (clone $monthlyInvoices)
->where('type', '=', 'offline')
->sum('net_price');
$online_sales = (clone $monthlyInvoices)
->where('type', '=', 'online')
->sum('net_price');
By cloning $monthlyInvoices, you are basically saying “don’t use the same query builder, but a new one that is identical”. This temporary query builder will only be used in this particular query and where('type', '=', 'offline') (or whatever you do) will not be “persisted” into the original $monthlyInvoices query builder.