如何修改CSV上传功能以读取额外行数据并格式化目标数组
Got it, let's work through this together to get your CSV upload and data formatting sorted exactly how you need it. Your CSV has a unique structure (header → cost prices → demand data) so we'll adjust the upload logic to capture that special price row, then reshape the data into your target array format.
Step 1: Adjust the CSV Upload Logic
First, we need to modify your existing upload code to separate the header row, cost price row, and demand data rows. This lets us store the cost prices separately for later use.
if ($this->request->data['file']['error'] === UPLOAD_ERR_OK){ $i = 1; $header = []; $costPrices = []; $demandData = []; $error_rows = []; if (($file = fopen($this->request->data['file']['tmp_name'], "r")) !== FALSE) { while (($row = fgetcsv($file, 0, ',', '"')) !== FALSE) { if ($i == 1){ // Grab the first row as the header $header = $row; } elseif ($i == 2) { // Second row is the cost prices for each cost type // Skip the "Date" column in the header to align with price row values $costTypeHeaders = array_slice($header, 1); if (count($costTypeHeaders) === count($row)) { $costPrices = array_combine($costTypeHeaders, $row); } else { // Add error if price row doesn't match the number of cost types $error_rows[] = [ 'row_content' => $row, 'message' => 'Price row has mismatched count with cost types' ]; } } else { // Rows 3+ are the actual demand data if (count($header) === count($row)){ $demandData[] = array_combine($header, $row); }else{ $error_rows[] = $row; } } $i++; } fclose($file); } }
Step 2: Reshape Data into Your Desired Format
Now that we have the demand data and cost prices stored separately, we can loop through each demand row and split it into individual entries for every cost type—matching the structure you specified.
$formattedArray = []; // Only proceed if we have valid data if (!empty($demandData) && !empty($costPrices)) { foreach ($demandData as $dataRow) { $currentDate = $dataRow['Date']; // Loop through each cost type and create a separate entry foreach (array_keys($costPrices) as $costType) { $formattedArray[] = [ 'date' => $currentDate, 'cost' => $costType, 'demand' => $dataRow[$costType], 'total' => $costPrices[$costType] ]; } } }
Full Combined Code
Here's the complete, integrated code that handles upload, data separation, formatting, and basic error checking:
if ($this->request->data['file']['error'] === UPLOAD_ERR_OK){ $i = 1; $header = []; $costPrices = []; $demandData = []; $error_rows = []; $formattedArray = []; if (($file = fopen($this->request->data['file']['tmp_name'], "r")) !== FALSE) { while (($row = fgetcsv($file, 0, ',', '"')) !== FALSE) { if ($i == 1){ $header = $row; } elseif ($i == 2) { $costTypeHeaders = array_slice($header, 1); if (count($costTypeHeaders) === count($row)) { $costPrices = array_combine($costTypeHeaders, $row); } else { $error_rows[] = [ 'row_content' => $row, 'message' => 'Price row count mismatch with cost types' ]; } } else { if (count($header) === count($row)){ $demandData[] = array_combine($header, $row); }else{ $error_rows[] = $row; } } $i++; } fclose($file); } // Generate the final formatted array if (!empty($demandData) && !empty($costPrices)) { foreach ($demandData as $dataRow) { $currentDate = $dataRow['Date']; foreach (array_keys($costPrices) as $costType) { $formattedArray[] = [ 'date' => $currentDate, 'cost' => $costType, 'demand' => $dataRow[$costType], 'total' => $costPrices[$costType] ]; } } } // Now you can iterate over $formattedArray to save each entry to your database // Example: // foreach ($formattedArray as $entry) { // $this->YourModel->save($entry); // } }
Quick Notes
- Error Handling: We added checks for mismatched row counts to catch invalid CSV data early.
- Reliability: Instead of using
array_keys/array_valueson generic elements, we directly map using the header names—this makes the code more robust if your CSV structure ever changes slightly. - Final Output: The
$formattedArraywill exactly match the structure you provided, with each cost type as a separate entry linked to its date, demand value, and total cost.
内容的提问来源于stack exchange,提问作者threeedv

