3

I am importing rims from an csv file to a webshop project. nothing for sell, just a personal project for learning how importers work. I am trying to map my $EANColumn variable to the first row field name in my csv.

So currently i have a csv with the following fields :

EAN;Brand;...and-more-comming


1234-WB;WheelBrand...and-more-comming


5678-BW;BrandWheel...and-more-comming


At the moment in my importer, it works when i map:

$EANColumn     = str_replace('’', '', $importData_arr["EAN"]);

And inserting it to my database through an array :

foreach($importData_arr as $importData){
           // var_dump($importData);
            $insertData = array(
                "EAN" =>$EANColumn);
            RimsUpload::insertData($insertData);

My complete code for this part is here :

if ($request->input('submit') != null ){

      $file = $request->file('file');

      // File Details
      $filename = $file->getClientOriginalName();
      $extension = $file->getClientOriginalExtension();
      $tempPath = $file->getRealPath();
      $fileSize = $file->getSize();
      $mimeType = $file->getMimeType();

      // Valid File Extensions
      $valid_extension = array("csv");

      // 2MB in Bytes
      $maxFileSize = 2097152;

      // Check file extension
      if(in_array(strtolower($extension),$valid_extension)){

        // Check file size
        if($fileSize <= $maxFileSize){

          // File upload location
          $location = 'uploads';

          // Upload file
          $file->move($location,$filename);

          // Import CSV to Database
          $filepath = url($location."/".$filename);

          // Reading file
          $file = fopen($filepath,"r");

          $importData_arr = array();
          $i = 0;

          while (($filedata = fgetcsv($file, 1000, ";")) !== FALSE) {
             $num = count($filedata );

             $EANColumn     = str_replace('’', '', $importData_arr["EAN"]);
             $BrandColumn   = $importData_arr["Brand"];

             // Skip first row (Remove below comment if you want to skip the first row)
             if($i == 0){
                $i++;
                continue;
             }

             for ($c=0; $c < $num; $c++) {
                $importData_arr[$i][] = $filedata [$c];
             }
             $i++;
          }
          fclose($file);

           dump($importData_arr);
          // Insert to MySQL database
          foreach($importData_arr as $importData){
           // var_dump($importData);
            $insertData = array(
                "EAN" =>$EANColumn,
               "Brand"=>$BrandColumn,
               "Name"=>$importData[2],
               "Size"=>$importData[3],
               "PCD"=>$importData[4],
               "Offset"=>$importData[5],
               "Bore"=>$importData[6],
               "Color"=>$importData[7],
               "Price"=>$importData[8],
               "Stock"=>$importData[9],
               "ImageURL"=>$importData[10]);
            RimsUpload::insertData($insertData);

          }

          Session::flash('message','Import Successful.');
        }else{
          Session::flash('message','File too large. File must be less than 2MB.');
        }

      }else{
         Session::flash('message','Invalid File Extension.');
      }

    }

    // Redirect to index
    // return redirect()->action("RimsUploadController@index", [$request]);
    return response()->redirectToAction('App\Http\Controllers\RimsUploadController@index', [$request]);
  }

But the real problem is that i do not want to map my columns like [0],[1],[2],[3]... I would like to take them from the first row colum name : ["EAN"],["Brand"],["Name"],["Size"]... So if EAN is column 1 or column 7, it wont make a difference, since it will detect it by name and not by row number. So it will then be able to handle files with different column orders.

When trying to do this, i get the error : Undefined index: EAN on $EANColumn = str_replace('’', '', $importData_arr["EAN"]);

The whole point is to make an easy way to import data from suppliers through csv into mysql. then display it to the webshop site.

5
  • in your input_data does it not numeric index key? can you var_dump your $importData_arr ? Commented Nov 19, 2020 at 13:37
  • just create an Mapper-class where you may be able to map your rows to its related name There you would be able also to apply some logic needed for your purposes ( myMapperClass->getValuesByBrandName(mybrandname) or whatever you want. Commented Nov 19, 2020 at 13:41
  • @Jerson array(0) { } Commented Nov 19, 2020 at 13:43
  • @ChristianFelix I am not sure what you mean by this, can you show me? Even if doing what i do, in a class. it will still return the error of undefined index Commented Nov 19, 2020 at 13:44
  • When you do not intend to apply special logic, use just this one: $test = ['a','b','c','d','e','f']; $result = array_combine($test,$row); Now your array has an key associated to your value Commented Nov 19, 2020 at 14:14

2 Answers 2

1

Before your while loop, extract the field names from the first row of your csv:

$file = fopen($filepath,"r");
$keys = fgetcsv($file, 1000, ';');

Then, fetch the data lines and combine the $keys array with the data into an associative array:

$importData_arr = [];
while ($line = fgetcsv($file, 1000, ';')) {
    $data = array_combine($keys, $line);
    // Do something with the data
    $data['EAN'] = str_replace('’', '', $data['EAN']);
    $importData_arr[] = $data;
}
fclose($file);

You can now access all data fields by their name, independent of the order in the CSV:

foreach($importData_arr as $importData){
    echo $importData['EAN'];
}

As long as the field names stay intact, you don't have to change your import code when the field order or count changes.

Sign up to request clarification or add additional context in comments.

4 Comments

@Michael Aggerholm: My first draft had a bug, fixed it!
why do i still need to define the offset "$importData_arr[0]" also. its a very nice solution, i added this. and everything seems fine, but i am getting the error : Undefined offset: 8. when adding 10 columns. i have double checked, nothing should be wrong, but it wont go higher than 7. any ideas?
@Michael Aggerholm: I skipped the foreach in my first example, so one had to specify an offset to access an element - see my updated answer with foreach loop like in your code.
@Michael Aggerholm: To address your second problem, just start debugging by var_dump'in fgetcsv line by line, there probably is some kind of error in your CSV file
0

Here is some simple proposal how to map your data to an array with given keys.

while ($row = fgetcsv($fp, 100, ',')) {

      $columnName = ['a','b','c','d','e','f'];
      $myRow = array_combine($columnName,$row);
    ....
 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.