How to use setcsvcontrol() - php

Good morning,
I'm developing a script to create a csv file. My problem is the delimiter of csv file, I need to use ";".
I read that I have to use "setcsvcontrol()" but I'm trying to use it and I haven't had any results.
This is a part of my script:
$create = fopen($fecha."p.csv", "a");
$file = new SplFileObject($fecha."p.csv");
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl(';');
foreach($cadena as $fields){
fputcsv($create,$fields);
}
Thanks.

SplFileObject::setCsvControl() only affects the object on which it was called, i.e. the $file object in your case. It does not affect the $create object that you got from fopen, even though both objects operate on the same file.
Either write to the $create object using fputcsv($handle, $fields, $delimiter, $enclosure), passing $create as first argument and the desired delimiter and enclosure as third and fourth arguments, or call $file->fputcsv(). In the latter case, you have to create the SplFileObject as writable using a suitable $open_mode.

Your not passing the delimiter to fputcsv;
fputcsv($create,$fields, ";");
you can also safely remove
$file = new SplFileObject($fecha."p.csv");
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl(';');
if you must use the SplFileObject Then change your code to.
$file = new SplFileObject("data.csv");
$file->setFlags(SplFileObject::WRITE_CSV);
$file->setCsvControl(';');
foreach ($rows as $row) {
$file->fputcsv($row);
}

Related

How convert a PHP array of associative array to a CSV string using a third composer vendor lib?

I must convert a php associative array to CSV like:
[
["a"=>1, "b"=>2, "c"=>3],
["a"=>5, "b"=>6, "c"=>6],
["a"=>7, "b"=>8, "c"=>9, "d"=>10]
]
must output a string like
a;b;c;d
1;2;3;
4;5;6;
7;8;9;10
I already implement this logic using only foreach and implodes. However CSV has some features like knowing when scape chars and when to quote cells.
I've been used https://www.papaparse.com/ (javascript) a lot for the front-end side.
Is there a Composer package which can do the job?
PS. I need the CVS as string not to save to a file.
You can use fputcsv to get properly formatted CSV, saving to memory and then save it to a variable:
$fh = fopen('php://memory', 'r+');
foreach($array as $row) {
fputcsv($fh, $row); // add other args as needed
}
$csv = stream_get_contents($fh, -1, 0);
//or
rewind($fh);
$csv = stream_get_contents($fh);
You can also use php://temp which will use memory up to a limit and then write to a temporary file or you can generate your own temporary file with tmpfile.

convert multiple json to php array

I have json file which contains multiple json objects.
Example
{"t":"abc-1","d":"2017-12-29 12:42:53"}
{"t":"abc-2","d":"2017-12-29 12:43:05"}
{"t":"abc-3","d":"2017-12-30 14:42:09"}
{"t":"code-4","d":"2017-12-30 14:42:20"}
Want to read this file and store into database, but I couldn't convert json to php array which further I can store into database.
I tried json_decode function, but its not working. I search for this but in every link its showing use json_decode. Below is my code
$filename = "folder/filename.json";
$data = file_get_contents($filename);
echo $data;
$tags = json_decode($data, true);
echo"<pre>";print_r($tags);exit;
$data is echoed but not the $tags.
Thanks in advance.
Make array of objects and use it later
$j = array_map('json_decode', file('php://stdin'));
print_r($j);
demo
If it's only four lines you can explode and json_decode each line and add it to an array.
$s = '{"t":"abc-1","d":"2017-12-29 12:42:53"}
{"t":"abc-2","d":"2017-12-29 12:43:05"}
{"t":"abc-3","d":"2017-12-30 14:42:09"}
{"t":"code-4","d":"2017-12-30 14:42:20"}';
$arr = explode(PHP_EOL, $s);
Foreach($arr as $line){
$json[] = json_decode($line,true);
}
Var_dump($json);
https://3v4l.org/97m0E
Multiple objects in a row should be enclosed in a json array and separated with comma like elements.So you need a [ ] at the start and end of the file.Also you could close the pre tag
Either you should fix the file generating that 'json' or you can use fgets to get one line at a time, and use json decode on every line
As pointed by other, JSON which you shared isn't valid. And, I think, it is stored in your file in same fashion. I would suggest to read this file line by line each line then you can decode.
$handle = fopen("folder/filename.json", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
$tags = json_decode($line, true);
echo"<pre>";print_r($tags);exit;
}
fclose($handle);
} else {
// error opening the file.
}
Assuming a file called `filename.json` contains the following lines
{"t":"abc-1","d":"2017-12-29 12:42:53"}
{"t":"abc-2","d":"2017-12-29 12:43:05"}
{"t":"abc-3","d":"2017-12-30 14:42:09"}
{"t":"code-4","d":"2017-12-30 14:42:20"}
So each one is a separate json entity
$filename = "folder/filename.json";
$lines=file( $filename );
foreach( $lines as $line ){
$obj=json_decode( $line );
$t=$obj->t;
$d=$obj->d;
/* do something with constituent pieces */
echo $d,$t,'<br />';
}
Your JSON is invalid, as it has multiple root elements
Fixing it like the following should work (note the [, ] and commas):
[
{"t":"abc-1","d":"2017-12-29 12:42:53"},
{"t":"abc-2","d":"2017-12-29 12:43:05"},
{"t":"abc-3","d":"2017-12-30 14:42:09"},
{"t":"code-4","d":"2017-12-30 14:42:20"}
]
If you cannot influence how the JSON file is created, you will need to create your own reader, as PHP is not built to support invalid formatting. You could separate the file by new lines and parse each one individually.

How to update csv column names with database table header

I am facing this problem some past days and now frustrate because I have to do it.
I need to update my CSV file columns name with database table header. My database table fields are different from CSV file. Now the problem is that first I want to update column name of CSV file with database table headers and then import its data with field mapping into database.
Please help me I don't know how I can solve this.
This is my php code:
$file = $_POST['fileName'];
$filename = "../files/" . $file;
$list = $_POST['str'];
$array_imp = implode(',', $list);
$array_exp = explode(',', $array_imp);
$fp = fopen("../files/" . $file, "w");
$num = count($fp);
for ($c = 0; $c < $num; $c++) {
if ($fp[c] !== '') {
fputcsv($fp, $array_exp);
}
}
fclose($fp);
require_once("../csv/DataSource.php");
$path = "../files/test_mysql.csv";
$dbtable = $ext[0];
$csv = new File_CSV_DataSource;
$csv->load($path);
$csvData = $csv->connect();
$res='';
foreach($csvData as $key)
{ print_r($key[1]);
$myKey ='';
$myVal='';
foreach($key as $k=>$v)
{
$myKey .=$k.',';
$myVal .="'".$v."',";
}
$myKey = substr($myKey, 0, -1);
$myVal = substr($myVal, 0, -1);
$query="insert into tablename($myKey)values($myVal)";
$res= mysql_query($query);
You have got an existing file of which the first line needs to be replaced.
This has been generally outlined here:
Overwrite Line in File with PHP
Some little explanation (and some tips that are not covered in the other question). Most often it's easier to operate with two files here:
The existing file (to be copied from)
A new file that temporarily will be used to write into.
When done, the old file will be deleted and the new file will be renamed to the name of the old file.
Your code does not work because you are already writing the new first line into the old file. That will chop-off the rest of the file when you close it.
Also you look misguided about some basic PHP features, e.g. using count on a file-handle does not help you to get the number of lines. It will just return 1.
Here is step by step what you need to do:
Open the existing file to read from. Just read the first line of it to advance the file-pointer (fgets)
Open a new file to write into. Write the new headers into it (as you already successfully do).
Copy all remaining data from the first file into the new, second file. PHP has a function for that, it is called stream_copy_to_stream.
Close both files.
Now check if the new file is what you're looking for. When this all works, you need to add some more steps:
Rename the original file to a new name. This can be done with rename.
Rename the file you've been written to to the original filename.
If you want, you then can delete the file you renamed in 5. - but only if you don't need it any longer.
And that's it. I hope this is helpful. The PHP manual contains example code for all the functions mentioned and linked. Good luck. And if you don't understand your own code, use the manual to read about it first. That reduces the places where you can introduce errors.
If you are managing to insert the table headers then you're half way there.
It sounds to me like you need to append the data after the headers something like:
$data = $headers;
if($fp[c]!=='')
{
$data .= fputcsv($fp, $array_exp);
}
Notice the dot '.' before the equals '=' in the if statement. This will add none blank $fp[c]values after the headers.

how to insert value in a particular location in csv file using php

Is it possible to write at a particular location in a CSV file using PHP?
I don't want to append data at the end of the CSV file. But I want to add data at the end of a row already having values in the CSV.
thanks in advance
No, it s not possible to insert new data in the middle of a file, due to filesystem nature.
Only append at the end is possible.
So, the only solution is to make another file, write a beginning part of source, append a new value, and then append the rest of the source file. And finally rename a resulting file to original name.
There you go. Complete working code:
<?php
//A helping function to insert data at any position in array.
function array_insert($array, $pos, $val)
{
$array2 = array_splice($array, $pos);
$array[] = $val;
$array = array_merge($array, $array2);
return $array;
}
//What and where you want to insert
$DataToInsert = '11,Shamit,Male';
$PositionToInsert = 3;
//Full path & Name of the CSV File
$FileName = 'data.csv';
//Read the file and get is as a array of lines.
$arrLines = file($FileName);
//Insert data into this array.
$Result = array_insert($arrLines, $PositionToInsert, $DataToInsert);
//Convert result array to string.
$ResultStr = implode("\n", $Result);
//Write to the file.
file_put_contents($FileName, $ResultStr);
?>
Technically Col. Shrapnel's answer is absolutely right.
Your problem is that you don't want to deal with all these file operations just to change some data. I agree with you. But you're looking for the solution in a wrong level. Put this problem in a higher level. Create a model that represents an entity in your CSV database. Modify the model's state and call its save() method. The method should be responsible to write your model's state in CSV format.
Still, you can use a CSV library that abstracts low level operations for you. For instance, parsecsv-for-php allows you to target a specific cell:
$csv = new parseCSV();
$csv->sort_by = 'id';
$csv->parse('data.csv');
# "4" is the value of the "id" column of the CSV row
$csv->data[4]['firstname'] = 'John';
$csv->save();

Contingency plan for fopen error in php

I'm writing a PHP app that has a 'control panel' that writes a prefs file with certain variables. On every POST, if the file doesn't exist, it is created. If it does exist, it is unlinked and a new file is touched with the same filename and new variables. This file is then included on another page with displays content based on the variables inside it.
$file = "phpsettings.php";
if (!file_exists($file)) {
touch($file);
$handle = fopen ($file, 'r+');
$str = "<?php \$pref1 = \"$mypref\"; ?>";
} else {
unlink($file);
touch($file);
$handle = fopen ($file, 'r+');
$str = "<?php \$pref1 = \"$mypref\"; ?>";
}
fwrite ($handle, $str);
fclose ($handle);
Is this a safe way of writing preferences, provided this file will be overwritten many times per day? What is a good way of both alerting the user of this control panel if the file wasn't saved correctly, and in that case, what would be a good contingency plan to avoid breaking the page this prefs file is included on short of defining a default set of variables to fill if !(file_exists)?
If you store your settings in an array, you can serialize() them and write to a text file, rather than writing raw php to a php file and including it.
If you're not sanitising your input for those preferences, and say $mypref1 represents someone's name, there's nothing stopping them from filling this out in the form field:
\"; echo \"PWNED
and your resulting PHP will become
<?php \$pref1 = \"$mypref\"; echo \"PWNED\"; ?>
So firstly, storing your preferences in an array and using serialize() is much safer:
$prefs = array('mypref1' => 'somethingorother');
$handle = fopen ($file, 'w');
fwrite($handle, serialize($prefs));
fclose($h);
// example code demonstrating unserialization
$prefs2 = unserialize(file_get_contents($file));
var_dump($prefs == $prefs2); // should output "(bool) true"
In your question, you also mention that if the file does exist, it is unlinked. You can simply truncate it to zero length by passing "w" as the second argument to fopen - you don't need to manually delete it. This should set the mtime anyway, negating the need for the call to touch().
If the values being written to the file are preferences, surely each preference could have a default, unless there are hundreds? array_merge will allow you to overwrite on a per-key basis, so if you do something like this:
// array of defaults
$prefs = array(
'mypref1' => 'pants',
'mypref2' => 'socks',
);
if (file_exists($file)) {
// if this fails, an E_NOTICE is raised. are you checking your server error
// logs regularly?
if ($userprefs = unserialize(file_get_contents($file))) {
$prefs = array_merge($prefs, $userprefs);
}
}
If the issue is that there are heaps, and you don't want to have to initialise them all, you could have a get_preference method which just wraps an isset call to the prefs array.
function get_preference($name, &$prefs) {
if (isset($pref[$name]))
return $pref[$name];
return null;
}
var_dump(get_preference('mypref1', $prefs));
Beyond all of the questions this raises though, the reality is that with your app, in the unlikely event that something does go wrong with the fopen, it should be regarded as a serious failure anyway, and the handful of users you're likely to have making use of this feature are going to be contacting you pretty darn quick if something goes wrong.
It is always better to store your users state in a session and only persist that state when needed.
Why not just use the truncation capabilities of fopen()? I believe instead of "r+", you'll need to pass "w+"... Then if the file exists, it will be truncated, if it doesn't you'll just create a new file. So the code becomes:
$file = "phpsettings.php";
$handle = fopen( $file, 'w+' );
$str = "<?php \$pref1 = \"$mypref\"; ?>";
fwrite ($handle, $str);
fclose ($handle);

Categories