问题
I am trying to read data from excel file and and then store it in database. but there is problem . sometimes file has a lot of data nearly 20000 records. when I try to process that request with that much data it process for 2 to 3 minutes and enter around 13000 record in database and after that request got failed. here is what i am doing . this process gets completed in five functions every functions has it own job. Now, I think I should do it by queue but i have no idea how it will work because I am returning some thing from every function which won't work in queue and there is also global array in my controller.
here is my controller. I think you don't need to read all the functions one by one just give me idea how I can achieve my goal
//global array variable declaration for import delivery Zone
protected $createdDeliveryZones;
protected $updatedDeliveryZones;
protected $errorDeliveryZones;
/**
* AddressController constructor.
*/
public function __construct()
{
parent::__construct();
$this->createdDeliveryZones = array();
$this->updatedDeliveryZones = array();
$this->errorDeliveryZones = array();
$this->middleware('staff.permissions', ['only' => ['index', 'create', 'edit', 'delete']]);
}
//delivery zone import function
public function importDeliveryZone(Request $request)
{
if ($request->isMethod('get')) {
return back();
}
$extension = $request->file('delivery_zone_file')->getClientOriginalExtension();
if($extension != 'csv')
{
return back()->with('error','Please Choose CSV File');
}
//getting spreadsheet data
$path = $request->file('delivery_zone_file')->getRealPath();
$spreadsheet = IOFactory::load($path);
$sheetData = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
//these variable will decide from where locations are starting in spreadsheet
$startAt = 2;
$endAt = count($sheetData);
$validation = 1;
// loop will fetch row and pass it to function row by row
foreach ($sheetData as $line_number => $delivery_zone) {
//fileformatevalidation function will return 1 or 0
if($line_number == 1){
// $validation = $this->fileFormatValidation($delivery_zone,$line_number);
if($validation == 0){
return back()->With('error','Please choose File with Correct Format');
}
}
else
{
if ($line_number >= $startAt && $line_number <= $endAt && array_filter($delivery_zone)) {
$this->extractDeliveryZones($delivery_zone,$line_number);
}
}
}
$errorDeliveryZones = $this->errorDeliveryZones;
$updatedDeliveryZones = $this->updatedDeliveryZones;
$createdDeliveryZones = $this->createdDeliveryZones;
return view('web.pages.transports.delivery_zones.import_delivery_zone_validation',compact('errorDeliveryZones',$errorDeliveryZones,'updatedDeliveryZones',$updatedDeliveryZones,'createdDeliveryZones',$createdDeliveryZones));
}
public function fileFormatValidation($delivery_zone)
{
if($delivery_zone['A'] != 'id' || $delivery_zone['B'] != 'postcode' || $delivery_zone['C'] != 'suburb' || $delivery_zone['D'] != 'state' || $delivery_zone['E'] != 'country' || $delivery_zone['F'] != 'income_rate_zone' || $delivery_zone['G'] != 'expense_rate_zone' || $delivery_zone['H'] != 'delivery_run' || $delivery_zone['I'] != 'carrier' || $delivery_zone['J'] != 'customer')
{
return 0;
}
else
{
return 1;
}
}
public function extractDeliveryZones($delivery_zone,$line_number)
{
$data_validation = 1;
//making array of location data
$deliveryZoneArray = array('id' => $delivery_zone['A'],'postcode' => $delivery_zone['B'], 'suburb' => $delivery_zone['C'], 'address_zone' => $delivery_zone['D'],'country' => $delivery_zone['E']);
// this function will validate data in excel sheet
Customer::where('name',$delivery_zone['J'])->exists() ? $deliveryZoneArray['apply_to_customer'] = Customer::where('name',$delivery_zone['J'])->first()->id : $deliveryZoneArray['apply_to_customer'] = null;
if(DeliveryRun::where('name',$delivery_zone['H'])->exists())
{
$deliveryZoneArray['delivery_run'] = DeliveryRun::where('name',$delivery_zone['H'])->first()->id;
}
else
{
$deliveryZoneArray['delivery_run'] = $delivery_zone['H'];
$deliveryZoneArray['reason'] = "Delivery Run Dosn't Exist";
array_push($this->errorDeliveryZones,$deliveryZoneArray);
return 1;
}
$data_validation = $this->importFileDataValidation($deliveryZoneArray);
if($data_validation == 1){
$this->createDeliveryZoneFromExcel($deliveryZoneArray);
}
}
public function createDeliveryZoneFromExcel($deliveryZoneArray)
{
if(empty($deliveryZoneArray['id']))
{
if(DeliveryZone::where('postcode',$deliveryZoneArray['postcode'])->where('suburb',$deliveryZoneArray['suburb'])->where('address_zone',$deliveryZoneArray['address_zone'])->exists())
{
$deliveryZoneArray['reason'] = "Duplicate postcode, suburb and state";
array_push($this->errorDeliveryZones,$deliveryZoneArray);
}
else
{
DeliveryZone::create($deliveryZoneArray);
array_push($this->createdDeliveryZones,$deliveryZoneArray);
}
}
else
{
if(DeliveryZone::where('id',$deliveryZoneArray['id'])->exists())
{
$delivery_run = DeliveryZone::find($deliveryZoneArray['id'])->update($deliveryZoneArray);
array_push($this->updatedDeliveryZones, $deliveryZoneArray);
}
else
{
$deliveryZoneArray['reason'] = "ID Doesn't Exist";
array_push($this->errorDeliveryZones,$deliveryZoneArray);
}
}
}
public function importFileDataValidation($deliveryZoneArray)
{
$countries = array('Australia');
if(empty($deliveryZoneArray['postcode']) || empty($deliveryZoneArray['suburb']) || empty($deliveryZoneArray['address_zone']))
{
$deliveryZoneArray['reason'] = 'Postcode, suburb or satate is Empty';
array_push($this->errorDeliveryZones,$deliveryZoneArray);
return 0;
}
else if(!in_array($deliveryZoneArray['country'],$countries))
{
$deliveryZoneArray['reason'] = 'Country not Found';
array_push($this->errorDeliveryZones,$deliveryZoneArray);
return 0;
}
else
{
return 1;
}
}
回答1:
Using Queues or Commands is good practise for time consuming tasks.
The response can either saved in the database and shown to the user in the next refresh, or shown using a service like Pusher and send with Broadcasting the response from the Queue to the frontend when the task is completed.
回答2:
I was using set_time_limit(200)
in every function related to this process that was my mistake I only have to use it in the first function. Now, its working fine
来源:https://stackoverflow.com/questions/61213529/how-to-process-time-taking-request-in-laravel