fputcsv() putting all data in one row - php

I'm working on reading some json, flattening it in to a single array, and then writing it to a csv. I've gotten pretty far but I am currently stuck on the last component. I'm able to pull the data, flatten it, and write it to the csv, but it for some reason it writes all of it in one row, while it should be creating a new line with each new object. I think it's happening because my flattened array is taking multiple objects and combining them in to one, but I cant figure out how to fix it. Any help would be greatly appreciated.
Here's what I have:
<?php
$csvArray = array();
function array_flatten($array, $prefix = 'new')
{
if (!is_array($array)) {
return false;
}
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, array_flatten($value, $prefix . '_' . $key));
} else {
$result[$prefix . '_' . $key] = $value;
}
}
return $result;
}
for ($x = 1; $x <= 1; $x++) {
$response = file_get_contents('https://seeclickfix.com/api/v2/issues?page=' . $x . '&per_page=2');
//Decode the JSON and convert it into an associative array.
$jsonDecoded = json_decode($response, true);
$flat = array_flatten($jsonDecoded['issues']);
//Give our CSV file a name.
$csvFileName = '/Applications/MAMP/htdocs/SeeClickFix/all_exports_3/export' . $x . '.csv';
//Open file pointer.
$fp = fopen($csvFileName, 'w');
foreach ($flat as $item) {
// fputcsv($fp, $item);
if (is_null($item) || !isset($item) || $item == "Point") {
} else {
array_push($csvArray, $item);
}
fputcsv($fp, $csvArray);
}
fclose($fp);
}
?>

Related

How to modify json to validate it?

I am downloading some json and merging them, but while doing that it creates a string like below,
}
][
{
I'd like to replace that with a comma in order to have a valid json
I tried something like this but it's not working:
$datas = array();
$json = str_replace("][",",", $datas);
$json = json_encode($json, JSON_PRETTY_PRINT);
print_r($json);
If I can manage to do that I'd use the same to replace columns name (I'm actually building this json from a csv) if possible.
UPDATE
To clarify I have multiple csv(s) from which I am then building a single json
FULL CODE
header('Content-Type: application/json');
$arr = array("04-12-2020",
"04-13-2020",
"04-14-2020",
"04-15-2020",
"04-16-2020",
"04-17-2020",
"04-18-2020",
"04-19-2020",
"04-20-2020",
"04-21-2020",
"04-22-2020",
"04-23-2020",
"04-24-2020",
"04-25-2020",
"04-26-2020",
"04-27-2020",
"04-28-2020",
"04-29-2020",
"04-30-2020",
"05-01-2020",
"05-02-2020",
"05-03-2020",
"05-04-2020",
"05-05-2020",
"05-06-2020",
"05-07-2020",
"05-08-2020",
"05-09-2020",
);
foreach($arr as $date) {
$url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports_us/".$date.".csv";
if (($handle = fopen($url, "r")) !== FALSE) {
$csvs = [];
while(! feof($handle)) {
$csvs[] = fgetcsv($handle);
}
$datas = [];
$column_names = [];
foreach ($csvs[0] as $single_csv) {
$column_names[] = $single_csv;
}
foreach ($csvs as $key => $csv) {
if ($key === 0) {
continue;
}
foreach ($column_names as $column_key => $column_name) {
$datas[$key-1][$column_name] = $csv[$column_key];
}
}
$json = json_encode($datas, JSON_PRETTY_PRINT);
fclose($handle);
print_r($json);
}
}
Don't call json_encode() inside the loop. Initialize $datas outside the loop, and encode it after the loop.
$datas = [];
foreach($arr as $date) {
$url = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_daily_reports_us/".$date.".csv";
if (($handle = fopen($url, "r")) !== FALSE) {
$csvs = [];
while($row = fgetcsv($handle)) {
$csvs[] = $row;
}
$column_names = [];
// Use header line to get array keys
foreach ($csvs[0] as $single_csv) {
$column_names[] = $single_csv;
}
array_shift($csvs); // remove header line
foreach ($csvs as $key => $csv) {
$new_data = [];
foreach ($column_names as $column_key => $column_name) {
$new_data[$column_name] = $csv[$column_key];
}
$datas[] = $new_data;
}
fclose($handle);
}
}
$json = json_encode($datas, JSON_PRETTY_PRINT);
print_r($json);

Wrote 2 functions, don't understand what I did wrong

I've been practicing PHP more and more and am trying to do functions daily to learn from them.
Yesterday I wrote 2 functions but they completely didn't work and I was looking for help as to why!
My code:
<?php
function getFilesAndContent($path)
{
$data[] = $fileData;
$folderContents = new DirectoryIterator($path);
foreach ($folderContents as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
$fileData = [
'file_name' => $fileInfo->getBasename(),
];
if ($fileInfo->getExtension()) {
$fileData['contents'] = getFileContents($fileInfo->getPathname());
}
$data = $fileData;
}
return $data;
}
function getFileContents($path)
{
$names = file_get_contents($fileInfo->getPathname());
$names = implode("\n", $names);
sort($names);
$contents = '';
foreach ($names as $name) {
$contents += $name . ' (' . strlen($name) . ')<br>';
}
return $contents;
}
foreach (getFilesAndContent('.') as $data) {
echo $data['file_name'];
echo '<br>';
echo $data['contents'];
echo '<hr>';
}
DISLCAIMER: I really would like to get these 2 functions to work BUT I already have a working alternative(thank you very much!) without any functions, this is meant as a learning opportunity for myself to improve, any help would be greatly appreciated!
You have several problems.
First, $data = $fileData; should be $data[] = $fileData;. Adding [] means that the assignment creates a new element in the array, rather than overwriting the entire variable. And when you initialize the variable at the beginning of getFilesAndContent, it should be $data = [];.
Second, file_get_contents($fileInfo->getPathname()) should be file_get_contents($path). $fileInfo is a variable in getFilesAndContent, not getFileContents.
Third, implode() should be explode(). implode joins an array to create a string, explode() splits up a string into an array.
function getFilesAndContent($path)
{
$data = [];
$folderContents = new DirectoryIterator($path);
foreach ($folderContents as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
$fileData = ['file_name' => $fileInfo->getBasename(),];
if ($fileInfo->getExtension()) {
$fileData['contents'] = getFileContents($fileInfo->getPathname());
}
$data[] = $fileData;
}
return $data;
}
function getFileContents($path)
{
$names = file_get_contents($path);
$names = explode("\n", $names);
sort($names);
$contents = '';
foreach ($names as $name) {
$contents += $name . ' (' . strlen($name) . ')<br>';
}
return $contents;
}
foreach (getFilesAndContent('.') as $data) {
echo $data['file_name'];
echo '<br>';
echo $data['contents'];
echo '<hr>';
}

How to convert $x['a']['b']['c'] = d to $x['a.b.c'] = d easily

I have a multiple level array field need to be submit via a form. Not sure what will be the easiest solution:
As php will auto convert dot to underscore, so i change it to array:
$form['a.b_b.c'] ==> <input name="a[b_b][c]" value="$form[a.b_b.c]">
And I got $_POST[a][b_b][c] correctly.
But what is the easiest way to assign this $_POST value back to the original $form['a.b_b.c'] without much loops? eg
$form['a.b_b.c'] = $_POST['a']['b_b']['c'];
Or is there a better way to walk around?
very close to this question but still not yet:
Convert dot syntax like "this.that.other" to multi-dimensional array in PHP
And here is my current solution:
foreach ($form as $k) {
$form[$k] = assign_val($_POST, $k);
}
function assign_val($arr = [], $key = '') {
$keys = explode('.', $key);
$val = &$arr;
foreach ($keys as $k) {
$val = &$val[$k];
}
return $val;
}
I would have a function flatten and do something like:
function flatten($array, $prefix = '') {
$result = array();
foreach($array as $key=>$value) {
if(is_array($value)) {
$result = $result + flatten($value, $prefix . $key . '.');
}
else {
$result[$prefix . $key] = $value;
}
}
return $result;
}
And then you can do:
$form = flatten($_POST);

Convert csv in php and get unique value

I would like to convert a csv file that has duplicate contents and i would like to sum the quantity and extract the price without sum it.
file.csv :
code,qty,price
001,2,199
001,1,199
002,2,159
002,2,159
Actual php that sum the quantiy and get a result with unique value and total qty.
<?php
$tsvFile = new SplFileObject('file.csv');
$tsvFile->setFlags(SplFileObject::READ_CSV);
$tsvFile->setCsvControl("\t");
$file = fopen('file.csv', 'w');
$header = array('sku', 'qty');
fputcsv($file, $header, ',', '"');
foreach ($tsvFile as $line => $row) {
if ($line > 0) {
if (isset($newData[$row[0]])) {
$newData[$row[0]]+= $row[1];
} else {
$newData[$row[0]] = $row[1];
}
}
}
foreach ($newData as $key => $value) {
fputcsv($file, array($key, $value), ',', '"');
}
fclose($file);
?>
the result for this is:
code,qty
001,3
002,4
and i would like to add price, but without sum it.
The result i need is:
code,qty,price
001,3,199
002,4,159
I haven't tested this yet, but I think this is what you are looking for:
<?php
$tsvFile = new SplFileObject('file.csv');
$tsvFile->setFlags(SplFileObject::READ_CSV);
$tsvFile->setCsvControl("\t");
$file = fopen('file.csv', 'w');
$header = array('sku', 'qty');
fputcsv($file, $header, ',', '"');
foreach ($tsvFile as $line => $row) {
if ($line > 0) {
if(!isset($newData[$row[0]])) {
$newData[$row[0]] = array('qty'=>0, 'price'=>$row[2]);
}
$newData[$row[0]]['qty'] += $row[1];
}
}
foreach ($newData as $key => $arr) {
fputcsv($file, array($key, $arr['qty'], $arr['price']), ',', '"');
}
fclose($file);
?>
To start with, there's a nice function on the PHP page str_getcsv which will help you end up with a more legible array to work with:
function csv_to_array($filename='', $delimiter=',') {
if(!file_exists($filename) || !is_readable($filename))
return FALSE;
$header = NULL;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE) {
while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
if(!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
fclose($handle);
}
return $data;
}
This is purely for legibility sake but now comes the code which would allow you to work over the array.
$aryInput = csv_to_array('file.csv', ',');
$aryTemp = array();
foreach($aryInput as $aryRow) {
if(isset($aryTemp[$aryRow['code'])) {
$aryTemp[$aryRow['code']['qty'] += $aryRow['qty'];
} else {
$aryTemp[$aryRow['code']] = $aryRow;
}
}
In the above code, it simply:
Loops through the input
Checks whether the key exists in a temporary array
If it does, it just adds the new quantity
If it doesn't, it adds the entire row
Now you can write out your expectant csv file :)

How to echo array elements that contain a variable —PHP

I have a script that looks through a file and returns every newline as an array element.
$file = fopen("dict.txt", "r");
$entries = array();
while (!feof($file)) { $entries[] = fgets($file); }
fclose($file);
I also have a script which does some utilities with a $_GET variable.
$word = htmlspecialchars($_GET["user"]);
$letters = $word[0] . $word[1] . $word[2];
What I would like to do now is to echo all elements in the $entries array beginning with $letters.
Any help would be much appreciated.
try
foreach($entries as $entry) {
if (strpos($entry, $letters) === 0) {
echo $entry;
}
}

Categories