简体   繁体   English

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

[英]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:我需要能够像这样编写 CSV :

+------------+-----------+--------------+-------------------+
| 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.困难的部分是telephoneemail列是动态的。 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.我想我正在寻找的是一种通用方法来获取如上所示的关联数组并转储表示使用数组键作为标题的 CSV 的字符串,请记住它们不会跨行匹配。

I have already tried passing such an array into fgetcsv() , and also tried the league/csv package, but neither of these support this.我已经尝试将这样的数组传递给fgetcsv() ,并且还尝试了league/csv package,但这些都不支持这一点。 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?有谁知道可以做到这一点的库,或者甚至可能只是一个 function 可以采用这种类型的数组并吐出正确的 CSV?

A bunch of foreach loops will work if you want to keep it dynamic:如果你想保持动态,一堆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);
}

Gives you:给你:

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
        )

)

If you want to just manually create the reference array, you can easily merge a blank array with the populated array and get a mixed array:如果您只想手动创建参考数组,您可以轻松地将空白数组与填充数组合并并获得混合数组:

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

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

Gives you:给你:

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] => 
        )
)

EDIT:编辑:

I am not sure if you needed an array to CSV function, but here's just a quick one:我不确定您是否需要 CSV function 的数组,但这里只是一个快速的:

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;
}

So after you have your array from one of the above-mentioned methods, just run this function before any other browser output:因此,从上述方法之一获得数组后,只需在任何其他浏览器 output 之前运行此 function:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM