2

I know this has been asked quite a few times but this is a bit of a twist.

I have a multidimensional array in which the Key of the array needs to be the column name for a flat csv-type string (I don't want it as a file, just as a csv string).

So it's like this:

$data = array(
                dates = array ('2010-01-02','2011-02-03','2011-02-04'),
                type1 = array ('data1','data2','data3'),
                type2 = array ('data4','data5','data6')
);

The end result should be:

$new_data  = "dates,type1,type2" . "\n"
$new_data .= "2010-01-02,data1,data4" . "\n"
$new_data .= "2011-02-03,data2,data5" . "\n"
$new_data .= "2011-02-04,data3,data6";

I hope this is clear. Thanks for any help.

julio
  • 6,360
  • 15
  • 57
  • 81

4 Answers4

1

Something like this would probably come close to what you want (not tested, just going off the top of my head):

$fh = fopen('file.csv', 'w');

// write out the headers
fputcsv($fh, array_keys($data));

// write out the data    
for ($i = 0; $i < count($data['dates']); $i++) {
    $temp = array($data['dates'][$i], $data['type1'][$i], $data['type2'][$i]);
    fputcsv($fh, $temp);
}
Marc B
  • 348,685
  • 41
  • 398
  • 480
  • thanks Marc-- that's sort of what I would have done but I need it as a string, not as a file. – julio Jul 06 '11 at 16:57
  • @marc-- thanks, but I am using this to feed data to a function, and don't want to leave data files laying around (or deal with cleanup). – julio Jul 06 '11 at 17:07
  • 1
    Open the file in memory instead on disk: `fopen('php://memory', 'rw')` – hakre Jul 06 '11 at 19:59
0

This is much more verbose than you'll likely ever need, but it allows you to have an array of n elements. zip is based off of the Python function of the same name. I did not write it.

$data = ($data);
$r = (call_user_func_array('zip', $data));

$fin = "";
$fin .= implode(',',array_keys($data)).PHP_EOL;
foreach($r as $arr)
{
    $fin .= implode(',',$arr).PHP_EOL;
}

// $fin now holds all the data. Do something with it and you're finished!

function zip() {
    $args = func_get_args();
    $zipped = array();
    $n = count($args);
    for ($i=0; $i<$n; ++$i) {
        reset($args[$i]);
    }
    while ($n) {
        $tmp = array();
        for ($i=0; $i<$n; ++$i) {
            if (key($args[$i]) === null) {
                break 2;
            }
            $tmp[] = current($args[$i]);
            next($args[$i]);
        }
        $zipped[] = $tmp;
    }
    return $zipped;
}

(check out the conversation in the comments. It's really relevant.)

Community
  • 1
  • 1
cwallenpoole
  • 76,131
  • 26
  • 124
  • 163
  • Just saying, this will not produce valid CSV as per RFC. – hakre Jul 06 '11 at 20:01
  • @hakre You're right, the proper line terminator is \r\n, which means the above will output valid CSV in Windows, but not *nix. – cwallenpoole Jul 06 '11 at 20:11
  • Uhm, imagine you have a value that contains a colon `,` or a linebreak or a quote `"` or even a mixture of such. I think the `PHP_EOL` is a minor issue compared to that. – hakre Jul 06 '11 at 20:13
  • Thought about that, but that does not fit with the OP's desired result. If he wanted, though, he could replace `$fin .= implode(',',$arr).PHP_EOL;` with `$fin .= '"' . implode('","',$arr)."\"\r\n";` – cwallenpoole Jul 06 '11 at 20:18
  • That said, use of PHP_EOL is incorrect for an actual CSV (instead of CSV-like), while failure to double quote is only ill-advised. – cwallenpoole Jul 06 '11 at 20:20
  • I ended up removing the PHP_EOL statements and using the "\r\n" as suggested above. – julio Jul 18 '11 at 17:23
0

I made a little class for doing this: https://gist.github.com/981720

You can include it and generate the csv like so:

CSV::export($field_names, $data, '', TRUE)

timw4mail
  • 1,626
  • 2
  • 12
  • 16
0

This is merely the same as Marc B suggested, however you wrote that you didn't wanted to create a file for this. Stream Wrappers to the rescue (not tested, just going off the top of my head):

$fh = fopen('php://memory', 'rw'); # don't create a file, write to memory instead

// write out the headers
fputcsv($fh, array_keys($data));

// write out the data    
for ($i = 0; $i < count($data['dates']); $i++) {
    $temp = array($data['dates'][$i], $data['type1'][$i], $data['type2'][$i]);
    fputcsv($fh, $temp);
}
rewind($fh);
$string = stream_get_contents($fh);
fclose($fh);
hakre
  • 184,866
  • 48
  • 414
  • 792