1

I have console app made in Symfony3, where user can import CSV file (which is validate) into database. I need to put records which haven't passed validation into separate file.

I use LeagueCSV to read CSV file and I try to use it to write unvalidated records but it doesn't work.

This is my code:

$reader = Reader::createFromPath($input->getArgument('lokalizacja'));
$reader->setDelimiter(';');
$reader->setHeaderOffset(0);

$results = $reader->getRecords();

foreach ($results as $row) {

  $year = $row['description'];

  $isValid = false;

  if ($row['qty'] > 0 && $row['price'] > 0 && !empty($row['mpn'])) {

      $isValid = true;

      $rok = filter_var($row['description'], FILTER_SANITIZE_NUMBER_INT);

            $product = (new Produkt())
                    ->setMpn($row['mpn'])
                    ->setQty($row['qty'])
                    ->setYear($year)
                    ->setPrice($row['price']);

            $this->em->persist($product); }

  if ($row['qty'] == 0 || $row['price'] == 0 || empty($row['mpn'])) {

       $writer = Writer::createFromPath('/path/to/saved/file.csv', 'w+');              
       $writer->insertOne([$row['mpn'], $row['qty'], $row['price'], 
                      $row['description']]);

        continue;
  }                
}

    $this->em->flush();

All records which passed validation are successfully saved in the database but I have problem with others records. In new CSV file I have only first, one record which haven't passed validation and nothing more. What am I doing wrong? I tried with

$writer->insertAll($results); //using an array

Or with if...else statment but that's nothing.

Also I made ...else statement where unvalidated records are saved in other table in database and its works but I don't know how to immediately convert them into CSV file.

3
  • 1
    Try moving $writer = Writer::createFromPath('/path/to/saved/file.csv', 'w+'); before the foreach loop Commented Jan 18, 2019 at 22:11
  • Oh god ;D It's finally works! Thank you so much! Commented Jan 18, 2019 at 23:48
  • Great! I added an answer Commented Jan 19, 2019 at 1:29

2 Answers 2

4

Don't know symfony but CSV output is pretty simple. FWIW...

Pass this an array, like a fetchall resultset.

<?php
public function outputCSV($data, $useKeysForHeaderRow = true) {
    if ($useKeysForHeaderRow) {
        array_unshift($data, array_keys(reset($data)));
    }

    $outputBuffer = fopen("php://output", 'w');
    foreach($data as $v) {
        fputcsv($outputBuffer, $v);
    }
    fclose($outputBuffer);
}

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="FooBarFileName_' . date('Ymd') . '.csv"');
header("Pragma: no-cache");
header("Expires: 0");
$this->outputCSV($results);
Sign up to request clarification or add additional context in comments.

Comments

2

If you look at the doc page for the writer you will see a warning at the top which states

When inserting records into a CSV document using League\Csv\Writer, first insert all the data that need to be inserted before starting manipulating the CSV. If you manipulate your CSV document before insertion, you may change the file cursor position and erase your data.

Your code calls

$writer = Writer::createFromPath('/path/to/saved/file.csv', 'w+');              
$writer->insertOne([$row['mpn'], $row['qty'], $row['price'], $row['description']]);

In every iteration the condition is met, this appears to be overwriting or dropping your previous insert every time. You should declare the $writer once before the loop starts in order to preserve each insert.

$writer = Writer::createFromPath('/path/to/saved/file.csv', 'w+');
foreach ($results as $row) { 
  // do stuff with $writer
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.