关联数组到 CSV,其中列是动态的

Associative array to CSV where columns are dynamic

给定一个这样的数组:

[
    [
        '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'
    ]
]

我需要能够像这样编写 CSV:

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

困难的部分是 telephoneemail 列是动态的。它们存在于某些行而不存在于其他行,并且可以有任意数量的这些字段仅存在于行的子集上。 do 共享某个字段的所有行都需要在同一列定位中包含该字段。 没有的行应该只有空单元格。

我想我正在寻找的是一种通用的方法来获取如上所示的关联数组并转储表示使用数组键作为 headers 的 CSV 的字符串,记住它们会跨行不匹配。

我已经尝试将这样的数组传递到 fgetcsv(), and also tried the league/csv 包中,但是这些都不支持。有谁知道可以执行此操作的库,或者甚至可能只是一个可以采用这种类型的数组并吐出正确的 CSV 的函数?

如果你想让它保持动态,一堆 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);