I have a process which loads multiple CSV files at a time, and may need to ignore these CSV files on subsequent runs (I don't control deletion of the files). As such I have a need to have a 'file' model to know when a file has been processed, and (the important bit!) I also need to store the related filename alongside each line of data as part of my import.
Was wondering if the filename for the import (passed in as the second param!) gets exposed in any way to the import class in App\Imports?
If it doesn't get exposed, you could always pass the filename as a param to the import.
See this comment for an example.
I am doing something similar like this, hope it helps.
class StageStockImport extends DefaultValueBinder implements ToModel, WithHeadingRow, WithCustomValueBinder, WithChunkReading, WithBatchInserts
{
protected $dataProviderCode;
protected $dataProviderName;
protected $fileName;
public function fromDataProvider(string $dpCode, string $dpName)
{
$this->dataProviderCode = $dpCode;
$this->dataProviderName = $dpName;
return $this;
}
public function fromFile(string $fileName)
{
$this->fileName = $fileName;
return $this;
}
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new StageStock([
'dp_code' => $this->dataProviderCode,
'dp_name' => $this->dataProviderName,
'stock_date' => (isset($row['date']) ? $this->transformDate(trim($row['date'])) : null),
'product_id' => (isset($row['product_id']) ? trim($row['product_id']) : null),
'product_description' => (isset($row['product_description']) ? trim($row['product_description']) : null),
'stock_qty' => (isset($row['stock']) ? trim($row['stock']) : 0),
'batch_number' => (isset($row['batch_number']) ? trim($row['batch_number']) : null),
'expire_date' => (isset($row['exp_date']) ? $this->transformDate(trim($row['exp_date'])) : null),
'file_name' => $this->fileName
]);
}
public function batchSize(): int
{
return 500;
}
public function chunkSize(): int
{
return 500;
}
}
Then I have a scheduled Console command doing this:
$allFiles = File::allFiles(storage_path('path/to/files'));
foreach ($allFiles as $file) {
$fileName = $file->getFilename();
$this->info(date('h:i:s') . ' Processing ' . $fileName);
StageStock::where('dp_code', '1010')->where('file_name', $fileName)->delete();
$import = (new StageStockImport())
->fromDataProvider('1010', 'DUMMY DATA PROVIDER')
->fromFile($fileName);
Excel::import($import, "path/to/files/$fileName", 'local', \Maatwebsite\Excel\Excel::XLSX);
}
Thanks guys for the quick response and working solutions!
Most helpful comment
I am doing something similar like this, hope it helps.
Then I have a scheduled Console command doing this: