Add new row in CSV using PHP - 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?

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);
?>

Related

How can I remove unwanted spaces from txt file

I'm trying to modify my txt file what I'm using in dokuwiki.
I generate timestamp on top of the txt file like this:
function filecont($file,$data)
{
$fileContents = file($file);
array_shift($fileContents);
array_unshift($fileContents, $data);
$newContent = implode("\n", $fileContents);
$fp = fopen($file, "w+");
fputs($fp, $newContent);
fclose($fp);
}
And my original txt file looks like this:
Now when I use my function:
$txt= "Last generated: " . date("Y M D h:i:s");
filecont($file,$txt);
I get a result like this:
Now I don't want to remove my ====== Open IoT book ======, it's probably because I don't have empty space in the first line?
But the worst problem that I have Is that is generates many empty spaces what I don't want.
I only want to get last generated at the top of the txt file and anything else untouched
I tested your code and removed the extra newlines by changing the line:
$fileContents = file($file);
to
$fileContents = file($file, FILE_IGNORE_NEW_LINES);
Adding the FILE_IGNORE_NEW_LINES flag stops a newline being added to each element/line.
http://php.net/manual/en/function.file.php.
I also removed the array_unshift(), which leaves '====== Open IoT book ======' in the file.
So my final function looked like this:
function filecont($file,$data)
{
$fileContents = file($file, FILE_IGNORE_NEW_LINES);
//array_shift($fileContents); Removed to preserve '====== Open IoT book ======' line.
array_unshift($fileContents, $data);
$newContent = implode("\n", $fileContents);
$fp = fopen($file, "w+");
fclose($fp);
}
Might just delete this line
array_shift($fileContents);
solve your problem?
when you get elements of file you need to check whether Last generated: is as your first row or not accordong to it yu need to use array_shift
$fileContents = file($file);
if(stripos($fileContents[0],"Last generated:") !== false)
{
array_shift($fileContents); //if found use shift
}
array_unshift($fileContents, $data);

File empty after fputcsv

I created a file with fputcsv
$handle = fopen('php://output', 'w+');
// Add the header of the CSV file
fputcsv($handle, array('Name', 'Surname', 'Age', 'Sex'), ';');
// Query data from database
// Add the data queried from database
foreach ($results as $result) {
fputcsv(
$handle, // The file pointer
array(...), // The fields
';' // The delimiter
);
}
file_put_contents('mycsv.csv',fgetcsv($handle), FILE_APPEND);
fclose($handle);
....
I want to save the output on mycsv.csv but the file is empty
The php://output is a stream that works like echo or print. It means, you are writing in the standard output (maybe, your console or the browser).
If you want to write your content in a csv file, try to open this file or create it using PHP directly, instead of use the file_put_contents.
$handle = fopen("mycsv.csv","wb");
fputcsv($handle, array('Name', 'Surname', 'Age', 'Sex'), ';');
//...put your code
rewind($handle);//optional.it will set the file pointer to the begin of the file

Creating csv file with php

I want to create a csv file, but when I run the code, it returns a blank page and no csv file. I use PHP 5.
I use the following code:
<?php
$data = array ('aaa,bbb,ccc,dddd',
'123,456,789',
'"aaa","bbb"');
$fp = fopen('data.csv', 'w');
foreach($data as $line){
$val = explode(",",$line);
fputcsv($fp, $val);
}
fclose($fp);
?>
Thank you!
Its blank because you are writing to file. you should write to output using php://output instead and also send header information to indicate that it's csv.
Example
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="sample.csv"');
$data = array(
'aaa,bbb,ccc,dddd',
'123,456,789',
'"aaa","bbb"'
);
$fp = fopen('php://output', 'wb');
foreach ( $data as $line ) {
$val = explode(",", $line);
fputcsv($fp, $val);
}
fclose($fp);
#Baba's answer is great. But you don't need to use explode because fputcsv takes an array as a parameter
For instance, if you have a three columns, four lines document, here's a more straight version:
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="sample.csv"');
$user_CSV[0] = array('first_name', 'last_name', 'age');
// very simple to increment with i++ if looping through a database result
$user_CSV[1] = array('Quentin', 'Del Viento', 34);
$user_CSV[2] = array('Antoine', 'Del Torro', 55);
$user_CSV[3] = array('Arthur', 'Vincente', 15);
$fp = fopen('php://output', 'wb');
foreach ($user_CSV as $line) {
// though CSV stands for "comma separated value"
// in many countries (including France) separator is ";"
fputcsv($fp, $line, ',');
}
fclose($fp);
Just in case if someone is wondering to save the CSV file to a specific path for email attachments. Then it can be done as follows
I know I have added a lot of comments just for newbies :)
I have added an example so that you can summarize well.
$activeUsers = /** Query to get the active users */
/** Following is the Variable to store the Users data as
CSV string with newline character delimiter,
its good idea of check the delimiter based on operating system */
$userCSVData = "Name,Email,CreatedAt\n";
/** Looping the users and appending to my earlier csv data variable */
foreach ( $activeUsers as $user ) {
$userCSVData .= $user->name. "," . $user->email. "," . $user->created_at."\n";
}
/** Here you can use with H:i:s too. But I really dont care of my old file */
$todayDate = date('Y-m-d');
/** Create Filname and Path to Store */
$fileName = 'Active Users '.$todayDate.'.csv';
$filePath = public_path('uploads/'.$fileName); //I am using laravel helper, in case if your not using laravel then just add absolute or relative path as per your requirements and path to store the file
/** Just in case if I run the script multiple time
I want to remove the old file and add new file.
And before deleting the file from the location I am making sure it exists */
if(file_exists($filePath)){
unlink($filePath);
}
$fp = fopen($filePath, 'w+');
fwrite($fp, $userCSVData); /** Once the data is written it will be saved in the path given */
fclose($fp);
/** Now you can send email with attachments from the $filePath */
NOTE: The following is a very bad idea to increase the
memory_limit and time limit, but I have only added to make sure if anyone faces the problem of connection time out or any other.
Make sure to find out some alternative before sticking to it.
You have to add the following at the start of the above script.
ini_set("memory_limit", "10056M");
set_time_limit(0);
ini_set('mysql.connect_timeout', '0');
ini_set('max_execution_time', '0');
In case someone is still looking for an answer (a simple one), here is the simple way of creating a csv with PHP.
//Let's say you want your csv file to have something like this:
**Title 1** | **Title 2** | **Title 3**
Value 1 | Value 2 | Value 3
Value 4 | Value 5 | Value 6
//create a variable and add your data to it
$data = "TITLE 1, TITLE 2, TITLE 3 \n";
$data .= val1 .",". val2 .",". val3 \n ;
$data .= val3 .",". val4 .",". val5 \n ;
//you can use a loop to add dynamic data to this variable, if you want.
//give your file a name.
$fileName = 'myData.csv';
//add the file path where you want to store your csv file
//you can use **$_SERVER['DOCUMENT_ROOT']** in your file path. Avoid using absoultue paths like **../** this
$filePath = 'your_path_to' . $fileName;
$fp = fopen($filePath, 'w+');
fwrite($fp, print_r($data, true));
//Once the data is written, it will be saved in the path given.
fclose($fp);
I think this is the shortest way
$columns = [
'id',
'product_name',
'product_url',
'price',
'category'
];
$products = [
[1, 'product 1', 'https://example.com/product-1', '9.99', 'category 1'],
[2, 'product 2', 'https://example.com/product-2', '19.99', 'category 2'],
[3, 'product 3', 'https://example.com/product-3', '29.99', 'category 3'],
[4, 'product 4', 'https://example.com/product-4', '39.99', 'category 4'],
];
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="products.csv"');
echo implode(',', $columns) . PHP_EOL;
foreach ($products as $product){
echo implode(',', $product) . PHP_EOL;
}

How to replace one line in php?

I have test.txt file, like this,
AA=1
BB=2
CC=3
Now I wanna find "BB=" and replace it as BB=5, like this,
AA=1
BB=5
CC=3
How do I do this?
Thanks.
<?php
$file = "data.txt";
$fp = fopen($file, "r");
while(!feof($fp)) {
$data = fgets($fp, 1024);
// You have the data in $data, you can write replace logic
Replace Logic function
$data will store the final value
// Write back the data to the same file
$Handle = fopen($File, 'w');
fwrite($Handle, $data);
echo "$data <br>";
}
fclose($fp);
?>
The above peace of code will give you data from the file and helps you to write the data back to the file.
Assuming that your file is structured like an INI file (i.e. key=value), you could use parse_ini_file and do something like this:
<?php
$filename = 'file.txt';
// Parse the file assuming it's structured as an INI file.
// http://php.net/manual/en/function.parse-ini-file.php
$data = parse_ini_file($filename);
// Array of values to replace.
$replace_with = array(
'BB' => 5
);
// Open the file for writing.
$fh = fopen($filename, 'w');
// Loop through the data.
foreach ( $data as $key => $value )
{
// If a value exists that should replace the current one, use it.
if ( ! empty($replace_with[$key]) )
$value = $replace_with[$key];
// Write to the file.
fwrite($fh, "{$key}={$value}" . PHP_EOL);
}
// Close the file handle.
fclose($fh);
The simplest way (if you are talking about a small file as above), would be something like:
// Read the file in as an array of lines
$fileData = file('test.txt');
$newArray = array();
foreach($fileData as $line) {
// find the line that starts with BB= and change it to BB=5
if (substr($line, 0, 3) == 'BB=')) {
$line = 'BB=5';
}
$newArray[] = $line;
}
// Overwrite test.txt
$fp = fopen('test.txt', 'w');
fwrite($fp, implode("\n",$newArray));
fclose($fp);
(something like that)
You can use Pear package for find & replace text in a file .
For more information read
http://www.codediesel.com/php/search-replace-in-files-using-php/

Trying to insert text into a file ABOVE a certain line

I have a text file, more of a users file for a program. Im trying to use PHP to insert new data before groups: in the file. The last user is above this line and i want to insert new users below the last user and above groups: in the file
Ive been tinkering and was trying some things, but i can only get it after that line.
heres what i have
$key = 'groups:';
$newline = 'blackberry';
//copy file to prevent double entry
$file = "data2.yml";
$newfile = "filetemp.txt";
copy($file, $newfile) or exit("failed to copy $file");
//load file into $lines array
$fc = fopen ($file, "r");
while (!feof ($fc))
{
$buffer = fgets($fc, 4096);
$lines[] = $buffer;
}
fclose ($fc);
//open same file and use "w" to clear file
$f=fopen($newfile,"w") or die("couldn't open $file");
/* uncomment to debug */
print_r($lines);
print "\n";
//loop through array using foreach
foreach($lines as $line)
{
fwrite($f,$line); //place $line back in file
if (strstr($line,$key)){ //look for $key in each line
fwrite($f,$newline."\n");
} //place $line back in file
}
fclose($f);
copy($newfile, $file) or exit("failed to copy $newfile");
?>
Its a yml file, so i cant add an extra line to post after or it screws up and refuses to run.
thanks!
your foreach code should be:
foreach($lines as $line)
{
if (strstr($line,$key)){ //look for $key in each line
fwrite($f,$newline."\n"); //insert data before line with key
}
fwrite($f,$line); //place $line back in file
}
This way you will write the new data first then the original data.

Categories