phpcsvfopenfwritefputcsv

Add new row in CSV using PHP


I want to append form data in a CSV file that is stored on the server, the data should be added as a new row. I tried

$list = array(
    'Peter,Griffin,Oslo,Norway,Norway,Norway,Norway,Norway',
    'Glenn,Quagmire,Oslo,Norway,Norway,Norway,Norway,Norway',
);
print_r($list);
$file = fopen('db.csv','a');  // 'a' for append to file - created if doesn't exit

foreach ($list as $line){
  fputcsv($file,explode(',',$line));
}

fclose($file); 

but can't add data at the end of the file. How can i achieve this?


Solution

  • You should open your CSV file in append mode fopen(FILENAME, 'a'); before calling fputcsv():

    <?php
    
    define('FILENAME', 'file.csv');
    
    $lines = [
       ['aaa', 'bbb', 'ccc'],
       ['123', '456', '789'],
       ['Quotes " get repeated twice', 'If commas , then it will be surounded by quotes', 'ccc'],
    ];
    
    // Fill the CSV file.
    $file = fopen(FILENAME, 'w');
    foreach ($lines as $fields) {
        fputcsv($file, $fields);
    }
    fclose($file);
    
    // Add a new line at the end of the file
    $file = fopen(FILENAME, 'a');
    fputcsv($file, ['another', 'line', 'at the end']);
    fclose($file);
    
    ?>
    

    It's important that you have write permission on the CSV file if not you won't be able to append data to it. The user and group of the file may not be the same as the PHP process. This depends a lot on your hosting service. The best would be to check that your SSH or FTP user is in the same group than the PHP running your web site. If both are in the same group then you can just give write permission to the user and group and only read for other users:

    chmod ug=rw,o=r db.csv
    

    Or even no read permission to other users, which would be even better:

    chmod ug=rw,o= db.csv
    

    Up to you to see what's the best to do. You can also change the user and group of the file with chown username db.csv or chgrp groupname db.csv or even chown username:groupname db.csv.

    Your code where I replaced the explode(',', $line) by preg_split('/\s*,\s*/', $line) in order to handle eventual spaces around the comma character:

    <?php
    
    // Just to see the var_export() in plain text instead of HTML.
    header('Content-Type: text/plain;charset=utf-8');
    
    // With spaces or tabs around the commas for the preg_split() demo.
    $lines = array(
        "Peter,\tGriffin,Oslo,   Norway,Norway  ,Norway, Norway,Norway",
        'Glenn, Quagmire, Oslo, Norway, Norway, Norway, Norway, Norway',
    );
    
    var_export($lines);
    
    $file = fopen('db.csv', 'a');
    
    foreach ($lines as $line) {
        fputcsv($file, preg_split('/\s*,\s*/', $line));
    }
        
    fclose($file);
    
    ?>