How can an associative multidimensional (multiple dimensions) PHP array get converted to downloadable CSV?
Get the solution ↓↓↓I have an associative multidimensional (dynamic length of dimensions) array. It originally comes from JSON data, but I understand that just makes things harder so I convert it usingjson_decode($original_data, true)
.
I'm interested to convert it to a clickable CSV file likeecho '<a href="data:application/csv, ' . $data . '">Click to download</a>'
.
I've tried many code variations, one of which I found online in https://coderwall.com/p/zvzwwa/array-to-comma-separated-string-in-php because its whole purpose is to "convert a multi-dimensional, associative array to CSV data". Alas, its code doesn't seem to be recursive. Unlike other functions I've tried it doesn't call itself recursively if the data isn'tis_array
.
Your assistance is appreciated.
Sample data:
$array = array(
'name' => 'Test',
'average' => 1,
'fp' => '',
'dates' => array(
'isScheduled' => '',
'startDate' => 1587418137,
'endDate' => 1587418137,
'pViewValue' => array(
'startDate' => '2020-04-20T18:28:57.000Z',
'endDate' => '2020-04-20T18:28:57.000Z',
)
)
);
echo '<pre>' . print_r($array, true) . '</pre>';
Array
(
[name] => Test
[average] => 1
[fp] =>
[dates] => Array
(
[isScheduled] =>
[startDate] => 1587418137
[endDate] => 1587418137
[pViewValue] => Array
(
[startDate] => 2020-04-20T18:28:57.000Z
[endDate] => 2020-04-20T18:28:57.000Z
)
)
)
Expected output:
name average fp dates-isScheduled date-StartDate date-endDate date-pViewValue-startDate date-pViewValue-endDate
test 1 1587418137 1587418137 2020-04-20T18:28:57.000Z 2020-04-20T18:28:57.000Z
Answer
Solution:
CSV is table-like: columns in rows, seperated by a seperator.
They are unsuitable to use for dynamic length and depth datastructures.
So the short answer is: No, don't.
However, if you happen to have some knowledge about WHAT to expect, you could predefine the 'meaning' of each column and map that to certain places inside your CSV structure. But that is trickery, and only works if you know what goes where.
Answer
Solution:
@nelsonrakson's answer led me to what was a very specific answer to a very general question.
Also, that answer didn't quote the header line, used blank columns for every parent title, used strings instead of arrays and thus was left with extra commas plus unneeded calls (like$csv_data .= "" . ",";
), so here it is with arrays, more proper support for parent titles and also what I wanted in the first place - an auto download of the CSV which was converted from an array:
Update: also added support for empty arrays like[something] => array()
.
<?php
$array = array(
'name of' => 'Test',
'average' => 1,
'fp' => '',
'dates' => array(
'isScheduled' => '',
'startDate' => 1587418137,
'endDate' => 1587418137,
'pViewValue' => array(
'startDate' => '2020-04-20T18:28:57.000Z',
'endDate' => '2020-04-20T18:28:57.000Z',
)
)
);
echo '<pre>' . print_r($array, true) . '</pre>';
$csv_title = array();
$csv_data = array();
array2csv($array, $csv_title, $csv_data);
$csv_title = implode(",", $csv_title);
$csv_data = implode(",", $csv_data);
echo $csv_title . "\n<br />" . $csv_data . "\n\n" . '
<script>
thevalue = \'' . $csv_title . "\\n\\\n" . $csv_data . '\'
var blob = new Blob([thevalue], {type: \'attachment/csv\'});
var blobUrl = URL.createObjectURL(blob);
var a = document.createElement("a");
with (a) {
// href="data:attachment/" + extension + ";charset=utf-8;base64," + utf8_to_b64(thevalue);
// href="data:text/" + save as + ";charset=\'utf-8\'," + thevalue;
href=blobUrl
download = "export.csv";
}
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
</script>
';
function str_wrap($string = '', $char = '"') {
return str_pad($string, strlen($string) + 2, $char, STR_PAD_BOTH);
}
function array2csv($array, &$csv_title, &$csv_data, $prefix = '') {
foreach($array as $key => $value) {
if (!empty($prefix) || strlen($prefix) > 0)
$key = $prefix . ' - ' . $key;
if (is_array($value) && !empty($value))
array2csv($value, $csv_title, $csv_data, $key);
else {
$csv_title[] = str_wrap($key);
$csv_data[] = !empty($value) ? str_wrap($value) : '';
}
}
}
?>
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: string literal contains an unescaped line break
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.