5

I appreciate there are already a lot of questions around this subject. But, as I'm not a PHP developer, I'm struggling to get anything to work for my specific object structure. I have a pretty flat JSON structure that is being read into PHP just fine. All I need to do is go through the array of objects, create the CSV headings from the keys in the first object (they are all the same), and then write each line of the CSV using all the object properties. Here's a look at my PHP data:

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
        )

So, you can see it should be pretty straightforward. The keys would be the CSV cell headings and then a row for each record.

I hope someone can help me. I don't know PHP at all.

UPDATE: Here's my latest PHP file. This works. I had to cast the Object to an Array to get the Keys:

<?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);
?>

Thank you everyone for the help. Amazing community!

Lee Probert
  • 10,308
  • 8
  • 43
  • 70

4 Answers4

10

For writing a PHP array to a CSV file you should use the built in PHP function 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);

Edit:

More specific example based on your data input:

<?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);

Edit 2:

Based on new information (you have a JSON string to start with), I'm added this example as a better way to write the data to a CSV file:

<?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);
ntzm
  • 4,663
  • 2
  • 31
  • 35
Rein
  • 3,211
  • 3
  • 16
  • 21
  • This is more like it! I'm nearly there. Am just struggling to get that initial array of the object keys. – Lee Probert Feb 12 '16 at 14:56
  • I update my last example with a fully dynamic way to also store your headers in the CSV. If you're gonna change the properties of your objects, the CSV is gonna follow with the right headers. Please note that it only takes properties from the first object in the array to build the CSV headers from. – Rein Feb 12 '16 at 15:04
  • Thanks dude. This was the help I needed. I had to tweak it a bit and am updating my question with the final PHP that works. – Lee Probert Feb 12 '16 at 15:04
  • Great! Glad to be of help. – Rein Feb 12 '16 at 15:05
  • Just a note: if you start with a JSON string and you want an array, just use `json_decode($string, TRUE)`. It will give you an array. – Rein Feb 12 '16 at 15:14
  • My answer got updated. Please use that code, the one I posted previously is simply wrong if you have a JSON string as input. I just don't want you to learn bad habits, because I advised you something wrong because a lack of information! – Rein Feb 12 '16 at 15:29
1

Try below solution header of csv will be (item, cost, approved by) - replace $data with your array variable:

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

for more detail have alook at : PHP: fputcsv - Manual

Chetan Ameta
  • 7,696
  • 3
  • 29
  • 44
  • I think my problem is that I have an array of Objects. I think I will need to flatten it out before it gets to the PHP so I can use this script. – Lee Probert Feb 12 '16 at 14:11
  • http://stackoverflow.com/questions/19495068/convert-stdclass-object-to-array-in-php – Rein Feb 12 '16 at 14:12
  • 1
    in foreach loop add one more new line: `$fields = (array) $fields` – Chetan Ameta Feb 12 '16 at 14:12
  • 1
    @ChetanAmeta I think it's worth noting that using this solution, the order of the values does matter. If you end up with writing a value in a different order then the previous one, even though you used the same key, it will still come under the wrong header in the CSV. Just wanted to highlight this. You could even be writing a completely different key for each fields row. Which makes it completely useless in my opinion. Why not just add the headers first then? – Rein Feb 12 '16 at 14:17
  • @Rein yes that can be done but according to question he want to use keys as header, also assuming that keys in his array is same – Chetan Ameta Feb 12 '16 at 14:19
  • @ChetanAmeta Fair enough. Just wanted to point that out based on the posted code. Good answer! – Rein Feb 12 '16 at 14:22
  • @rein - thanks. That is the code I need. I just don't know how to integrate it into yours. – Lee Probert Feb 12 '16 at 14:38
  • @LeeProbert I updated my answer below with a more specific solution. Please look into that – Rein Feb 12 '16 at 14:46
1

I've created a function for that before. Bare in mind the code bellow does not assume there is any csv headers.

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"));

If this is not what you're asking for let me know, I'll edit the answer.

André Ferraz
  • 1,511
  • 11
  • 29
0

You can try below code to write data to 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);
rsmdh
  • 128
  • 1
  • 2
  • 12