首页 > 解决方案 > Associative array to CSV where columns are dynamic

问题描述

Given an array such as this:

[
    [
        'first_name' => 'Bill',
        'last_name' => 'Johnson',
        'telephone' => '123-456-7890'
    ],
    [
        'first_name' => 'Kurtis',
        'last_name' => 'Wild',
        'telephone' => '321-654-0987'
    ],
    [
        'first_name' => 'Jane',
        'last_name' => 'Doe',
        'email' => 'janedoe@gmail.com'
    ]
]

I need to be able to write a CSV like so:

+------------+-----------+--------------+-------------------+
| first_name | last_name |  telephone   |       email       |
+------------+-----------+--------------+-------------------+
| Bill       | Johnson   | 123-456-7890 |                   |
| Kurtis     | Wild      | 321-654-0987 |                   |
| Jane       | Doe       |              | janedoe@gmail.com |
+------------+-----------+--------------+-------------------+

The difficult part is that the telephone and email columns are dynamic. They exist for some rows but not others, and there can be any number of these fields that exist only on a subset of rows. All of the rows that do share a certain field need to have that field in the same column positioning. The rows that do not have this field should just have empty cells.

I guess what I'm looking for is a generic way to take an associative array as shown above and dump out a string representing a CSV that uses the array keys as headers, keeping in mind they will not match across rows.

I have already tried passing such an array into fgetcsv(), and also tried the league/csv package, but neither of these support this. Does anybody know a library that can do this, or perhaps even just a function that can take this type of array and spit out a correct CSV?

标签: phpcsvdynamicassociative-array

解决方案


foreach如果你想保持动态,一堆循环将起作用:

# Create a key storage array
$cols   =   [];
foreach($arr as $row) {
    foreach($row as $k => $v) {
        if(!in_array($k, $cols))
            $cols[$k] =   '';
    }
}
# Loop the main array again and merge the storage array
foreach($arr as $k => $row) {
    $arr[$k]    =   array_merge($cols, $row);
}

给你:

Array
(
    [0] => Array
        (
            [first_name] => Bill
            [last_name] => Johnson
            [telephone] => 123-456-7890
            [email] => 
        )

    [1] => Array
        (
            [first_name] => Kurtis
            [last_name] => Wild
            [telephone] => 321-654-0987
            [email] => 
        )

    [2] => Array
        (
            [first_name] => Jane
            [last_name] => Doe
            [telephone] => 
            [email] => janedoe@gmail.com
        )

)

如果您只想手动创建参考数组,您可以轻松地将空白数组与填充数组合并并获得混合数组:

$cols   =   [
    'first_name' => '',
    'last_name' => '',
    'email' => '',
    'telephone' => ''
];

foreach($arr as $k => $row) {
    $arr[$k]    =   array_merge($cols, $row);
}

给你:

Array
(
    [0] => Array
        (
            [first_name] => Bill
            [last_name] => Johnson
            [email] => 
            [telephone] => 123-456-7890
        )

    [1] => Array
        (
            [first_name] => Kurtis
            [last_name] => Wild
            [email] => 
            [telephone] => 321-654-0987
        )

    [2] => Array
        (
            [first_name] => Jane
            [last_name] => Doe
            [email] => janedoe@gmail.com
            [telephone] => 
        )
)

编辑:

我不确定您是否需要 CSV 函数的数组,但这只是一个快速的:

function downloadCSV($rows)
{
    ob_start();
    $fp = fopen('php://output', 'w');
    foreach ($rows as $fields) {
        fputcsv($fp, $fields);
    }
    fclose($fp);
    $str    =   ob_get_contents();
    ob_end_clean();
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.date('YmdHis').'file.csv"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: '.strlen($str));
    echo $str;
    exit;
}

因此,从上述方法之一获得数组后,只需在任何其他浏览器输出之前运行此函数:

# $arr being your array of course
downloadCSV($arr);

推荐阅读