如何将关联多维(多维)PHP数组转换为可下载的CSV?

如何将关联多维(多维)PHP数组转换为可下载的CSV?,php,multidimensional-array,export-to-csv,associative-array,Php,Multidimensional Array,Export To Csv,Associative Array,我有一个关联多维(维度的动态长度)数组。它最初来自JSON数据,但我知道这会让事情变得更难,所以我使用JSON\u decode($original\u data,true)对其进行转换 我有兴趣将其转换为可点击的CSV文件,如echo' 我尝试了许多代码变体,其中一个是我在网上找到的,因为它的全部目的是“将多维关联数组转换为CSV数据”。唉,它的代码似乎不是递归的。与我尝试过的其他函数不同,如果数据不是数组,它不会递归调用自身 谢谢你的帮助 样本数据: $array = array(

我有一个关联多维(维度的动态长度)数组。它最初来自JSON数据,但我知道这会让事情变得更难,所以我使用
JSON\u decode($original\u data,true)
对其进行转换

我有兴趣将其转换为可点击的CSV文件,如
echo'

我尝试了许多代码变体,其中一个是我在网上找到的,因为它的全部目的是“将多维关联数组转换为CSV数据”。唉,它的代码似乎不是递归的。与我尝试过的其他函数不同,如果数据不是
数组,它不会递归调用自身

谢谢你的帮助

样本数据:

$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
                )

        )
)

CSV类似于表格:行中的列,由分隔符分隔

它们不适合用于动态长度和深度数据结构

所以简单的回答是:不,不要

但是,如果您碰巧对预期内容有所了解,则可以预定义每个列的“含义”,并将其映射到CSV结构中的某些位置。 但这是一种骗局,只有当你知道该怎么做才行

<?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) : '';
        }
    }
}
?>


@nelsonrakson的回答让我想到了一个非常普遍的问题

此外,该答案没有引用标题行,对每个父标题使用空白列,使用字符串而不是数组,因此留下了额外的逗号和不必要的调用(如
$csv_data.='',“;
),因此这里是数组,更恰当地支持父标题,以及我首先想要的内容—从阵列转换而来的CSV自动下载:

更新:还添加了对空数组的支持,如
[something]=>array()


如何完成我添加到问题中的输出?也就是说,根据上面数组的键添加前缀?@LWC确定有效。但是如果它有5层深,你会添加所有的前缀吗?这是可以做到的,但我内心的每件事都在呼喊:不要使用CSV。它就是不适合。JSON编码听起来更可行。是的,我添加了所有5个。JSON不适用于最终用户。CSV是。所有这些都是为需要生成文件以供下载的最终用户准备的。谢谢,我在回答中使用了您的链接作为参考。@LWC我很高兴!还添加了对空数组的支持,如
[something]=>array()
fputcsv()
<?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) : '';
        }
    }
}
?>