从 PHP 数组编写 CSV 文件

Write a CSV file from a PHP Array

提问人:Lee Probert 提问时间:2/12/2016 最后编辑:Lee Probert 更新时间:11/10/2022 访问量:20967

问:

我很欣赏围绕这个主题已经有很多问题。但是,由于我不是PHP开发人员,我正在努力使任何东西都适用于我的特定对象结构。我有一个非常扁平的JSON结构,可以很好地读入PHP中。我需要做的就是遍历对象数组,从第一个对象中的键创建 CSV 标题(它们都相同),然后使用所有对象属性编写 CSV 的每一行。下面是我的PHP数据:

Array
(
    [0] => stdClass Object
        (
            [record id] => -KA9S-beTbe9LIPBm_xK
            [timestamp] => Wed Feb 10 2016 10:12:20 GMT+0100
            [user id] => 33037t23nxyx1x5k
            [user age] => 18-24
            [user gender] => M
            [user q1] => Yes
            [user q2] => Yes
            [user q3] => more
            [answer q1 value] => 1
            [answer q1 confidence] => 3
            [answer q1 duration] => 262412
            [answer q2 value] => 1
            [answer q2 confidence] => 3
            [answer q2 duration] => 1959
            [answer q3 value] => 0
            [answer q3 confidence] => 3
            [answer q3 duration] => 2939
            [answer q4 value] => 1
            [answer q4 confidence] => 2
            [answer q4 duration] => 1868
            [answer q5 value] => 1
            [answer q5 confidence] => 2
            [answer q5 duration] => 2196
        )

所以,你可以看到它应该非常简单。键将是 CSV 单元格标题,然后是每条记录的一行。

我希望有人能帮助我。我根本不懂PHP。

更新:这是我最新的PHP文件。这行得通。我必须将对象转换为数组才能获得键:

<?php

    $data = $_POST['data'];
    $response = json_decode($data);

    $records_arr = $response->records;

    $fp = fopen('records.csv', 'w');
    $i = 0;

    foreach ($records_arr as $record) {


        // $record is an object so create an array
        $record_arr = array();

        foreach ($record as $value) {
            $record_arr[] = $value;
        }

        if($i == 0){
            fputcsv($fp, array_keys((array)$record));
        }
        fputcsv($fp, array_values($record_arr));
        $i++;
    }

    fclose($fp);

    echo print_r($records_arr);
?>

谢谢大家的帮助。了不起的社区!

php csv fopen

评论


答:

1赞 Chetan Ameta 2/12/2016 #1

尝试以下 csv 的解决方案标头将是 (item, cost, approved by) - 替换为您的数组变量:$data

$data = array(
    array( 'item' => 'Server', 'cost' => 10000, 'approved by' => 'Joe'),
    array( 'item' => 'Mt Dew', 'cost' => 1.25, 'approved by' => 'John'),
    array( 'item' => 'IntelliJ IDEA', 'cost' => 500, 'approved by' => 'James')
);

$fp = fopen('file.csv', 'w');
$i = 0;
foreach ($data as $fields) {
    if($i == 0){
        fputcsv($fp, array_keys($fields));
    }
    fputcsv($fp, array_values($fields));
    $i++;
}

fclose($fp);

有关更多详细信息,请查看: PHP: fputcsv - Manual

评论

0赞 Lee Probert 2/12/2016
我认为我的问题是我有一个对象数组。我想我需要在它到达 PHP 之前将其扁平化,以便我可以使用此脚本。
1赞 Chetan Ameta 2/12/2016
在 foreach 循环中,再添加一行新行:$fields = (array) $fields
1赞 Rein 2/12/2016
@ChetanAmeta 我认为值得注意的是,使用此解决方案,值的顺序确实很重要。如果您最终以与前一个值不同的顺序写入一个值,即使您使用了相同的键,它仍然会在 CSV 中位于错误的标头下。只是想强调这一点。您甚至可以为每个字段行编写一个完全不同的键。在我看来,这使得它完全没用。为什么不先添加标题呢?
0赞 Chetan Ameta 2/12/2016
@Rein是的,这是可以做到的,但根据问题,他想使用键作为标头,也假设他的数组中的键是相同的
10赞 Rein 2/12/2016 #2

要将PHP数组写入CSV文件,您应该使用内置的PHP函数:fputcsv

<?php

$list = array (
    array('header 1', 'header 2', 'header 3', 'header 4'),
    array('5656', '454545', '5455', '5454'),
    array('541212', '454545', '5455', '5454'),
    array('541212', '454545', '5455', '5454'),
);

$fp = fopen('file.csv', 'wb');

foreach ($list as $fields) {
    fputcsv($fp, $fields);
}

fclose($fp);

编辑:

基于您的数据输入的更具体示例:

<?php

// I had to recreate your data, this is just an example
$array_of_objects = array();
for( $i = 0; $i < 5; $i++ )
{
    $obj = new \stdClass();
    $obj->username = "Rein";
    $obj->answer = "Correct";
    $obj->awesomeness = 1000;

    $array_of_objects[] = $obj;
}

// Open a file to write to
$fp = fopen('file.csv', 'wb');

$i = 0;

// Loop the array of objects
foreach( $array_of_objects as $obj )
{
    // Transform the current object to an array
    $fields = array();

    foreach ($obj as $k => $v)
    {
        $fields[ $k ] = $v;
    }

    if( $i === 0 )
    {
        fputcsv($fp, array_keys($fields) ); // First write the headers
    }

    fputcsv($fp, $fields); // Then write the fields

    $i++;
}

fclose($fp);

编辑2:

根据新信息(你有一个 JSON 字符串开始),我添加了这个示例,作为将数据写入 CSV 文件的更好方法:

<?php

$data = json_decode($_POST['data'], TRUE);
$records = $data['records'];

$fp = fopen('records.csv', 'wb');

$i = 0;
foreach ($records as $record) {

    if($i === 0) {
        fputcsv($fp, array_keys($record));
    }

    fputcsv($fp, array_values($record));
    $i++;
}

fclose($fp);

评论

0赞 Lee Probert 2/12/2016
这更像是它!我快到了。我只是在努力获取对象键的初始数组。
0赞 Rein 2/12/2016
我用一种完全动态的方式更新了我的最后一个示例,以将您的标头存储在 CSV 中。如果要更改对象的属性,CSV 将遵循正确的标题。请注意,它仅从数组中的第一个对象中获取属性,以便从中构建 CSV 标头。
0赞 Lee Probert 2/12/2016
谢谢伙计。这是我需要的帮助。我不得不稍微调整一下,并用最终有效的PHP更新我的问题。
0赞 Rein 2/12/2016
伟大!很高兴能帮上忙。
0赞 Rein 2/12/2016
请注意:如果您以 JSON 字符串开头并且想要一个数组,只需使用 .它会给你一个数组。json_decode($string, TRUE)
1赞 André Ferraz 2/12/2016 #3

我之前为此创建了一个函数。请记住,下面的代码不假定有任何 csv 标头。

function doCSV($file, $content = array())
{
    $handle =  fopen($file, "w");
    foreach($content as $value) {
        fputcsv($handle, array(key($content), $value));
    }

    fclose($handle);
}

doCSV("test.csv", array("Test 1" => "Value 1", "Test 2" => "Value 2"));

如果这不是您要求的,请告诉我,我会编辑答案。

评论

0赞 Lee Probert 2/12/2016
我的问题是我有一个对象数组。因此,我需要将它们解包到一个数组中才能正常工作。我认为。
0赞 André Ferraz 2/12/2016
@LeeProbert至少能提供数据的来源?
0赞 Lee Probert 2/12/2016
数据结构是从json解码的。我已经更新了我的 PHP。
0赞 André Ferraz 2/12/2016
@LeeProbert,如果您共享了 JSON 数据,您现在应该已经有了解决方案
0赞 Rein 2/12/2016
我早就知道你有一个JSON字符串,我们不会将对象数组转换为数组。我们只是告诉您设置第二个参数,该参数返回数组。json_decodeTRUE
0赞 rsmdh 11/9/2022 #4

您可以尝试以下代码将数据写入 csv

ob_start();
$outputCsv = fopen('export-csv.csv'', 'wb');
fputcsv($outputCsv, ['column header 1', 'column header 2', 'column header 3', 'column header 4'], ",");
$arOutput = [
  ['1', '2', '3', '4'],
  ['4', '6', '2', '0'],
  ['4', '6', '3', '2'],
  ['4', '7', '3', '3'],
  ['4', '3', '2', '4'],
  ['4', '4', '8', '1'],
]
foreach ($arOutput as $r)
{
    fputcsv($outputCsv, $r, ",");
}
fclose($outputCsv);