2

I'm trying to create a multidimensional array in PHP where the inner arrays are associative for the following example CSV string $csv:

# Results from 2015-06-16 to 2015-06-16.
date,time,label,artist,composer,album,title,duration
2015-06-16,12:00 AM,Island,U2,"Clayton- Adam,The Edge,Bono,Mullen- Larry- Jr",Songs Of Innocence,SONG FOR SOMEONE,03:46
2015-06-16,12:04 AM,Lowden Proud,"Fearing & White, Andy White, Stephen Fearing","White- Andy,Fearing- Stephen",Tea And Confidences,SECRET OF A LONG LASTING LOVE,03:10
2015-06-16,12:07 AM,Columbia,The Wallflowers,"Dylan- Jakob,Irons- Jack,Mathis- Stuart,Richling- Greg,Jaffee- Rami",Glad All Over,REBOOT THE MISSION,03:31
2015-06-16,12:10 AM,Distort Light,Bend Sinister,Moxon- Daniel,"Stories Of Brothers, Tales Of Lovers",JIMMY BROWN,03:48

The number of actual data rows following the 3rd+ row format is variable. What I have done so far is made a plain multidimensional array:

$resultArray = str_getcsv($csv, PHP_EOL);//parse the rows
array_shift($resultArray);//shift out results first row: date info
array_shift($resultArray);//shift out results new first row: field labels
foreach($resultArray as &$row) {//parse the items in rows
    $row = str_getcsv($row, ",", '"');//removes the '"' field enclosure?
}//foreach

This makes a functional multidimensional array but what I can't figure out is how to make the inner arrays associative so I can access them using the text friendly keys from the array I anticipated using:

$rowFieldKeysArray = array('date', 'time', 'label', 'artist', 'composer', 'album', 'title', 'duration');

I'm sure there's a simple PHP way to use the key name array as the keys for an associative array but I'm not sure how to do that. I rather suspect I need to something along the lines of:

foreach($resultArray as $rowKey => &$row) {
    $row[$rowFieldKeysArray[$rowKey]] = str_getcsv($row, ",", '"');
}//foreach

But this yields a "Warning: Illegal string offset 'date'[...]".

How would I do this?

EDIT: based on the combined information provided by the link in Andrew's comment and the in the answer I accepted, I was able to solve this problem using the following efficient code:

    $resultArray = str_getcsv($csv, PHP_EOL);//parse the rows
    array_shift($resultArray);//shift out results first row: date info
    $rowFieldKeysArray = str_getcsv( array_shift($resultArray), "," );//shift out results new first row: field labels into field key name array
    //array('date', 'time', 'label', 'artist', 'composer', 'album', 'title', 'duration');//array of Key field names for associative array
    //       [0]     [1]      [2]      [3]        [4]        [5]      [6]       [7]      //key index
    foreach($resultArray as &$row) {//parse the items in rows
        $row = array_combine($rowFieldKeysArray, str_getcsv($row, ",", '"'));//array_combine replaces numeric indexes with key field labels
    }//foreach

Thank you!

BartmanEH
  • 222
  • 2
  • 13

1 Answers1

6

This may help you

Script - For csv to array from file

[akshay@localhost tmp]$ cat test.php
<?php

function csv_to_array($filename='', $delimiter=',')
{
    if(!file_exists($filename) || !is_readable($filename))
        return FALSE;

    $header = NULL;
    $data = array();
    if (($handle = fopen($filename, 'r')) !== FALSE)
    {
        while (($row = fgetcsv($handle, 0, $delimiter)) !== FALSE)
        {

            if(!$header)
            {
               $header = $row;
            }
            else
            {
                if(count($header)!=count($row)){ continue; }

                $data[] = array_combine($header, $row);
            }
        }
        fclose($handle);
    }
    return $data;
}

print_r(csv_to_array("/tmp/test.csv"));

?>

Script - For csv to array from string

[akshay@localhost tmp]$ cat test.php
<?php

function str_to_csv_to_array($string, $delimiter=',')
{
        $header = NULL;
        $data = array();
        $rows = explode(PHP_EOL, $string); 
        foreach($rows as $row_str)
        {
            $row = str_getcsv($row_str);
            if(!$header)
            {
               $header = $row;
            }
            else
            {
                if(count($header)!=count($row)){ continue; }

                $data[] = array_combine($header, $row);
            }
        }

    return $data;
}


$string = <<<EOF
date,time,label,artist,composer,album,title,duration
2015-06-16,12:00 AM,Island,U2,"Clayton- Adam,The Edge,Bono,Mullen- Larry- Jr",Songs Of Innocence,SONG FOR SOMEONE,03:46
2015-06-16,12:04 AM,Lowden Proud,"Fearing & White, Andy White, Stephen Fearing","White- Andy,Fearing- Stephen",Tea And Confidences,SECRET OF A LONG LASTING LOVE,03:10
2015-06-16,12:07 AM,Columbia,The Wallflowers,"Dylan- Jakob,Irons- Jack,Mathis- Stuart,Richling- Greg,Jaffee- Rami",Glad All Over,REBOOT THE MISSION,03:31
2015-06-16,12:10 AM,Distort Light,Bend Sinister,Moxon- Daniel,"Stories Of Brothers, Tales Of Lovers",JIMMY BROWN,03:48
EOF;

print_r(str_to_csv_to_array($string));
?>

Input file

[akshay@localhost tmp]$ cat test.csv
date,time,label,artist,composer,album,title,duration
2015-06-16,12:00 AM,Island,U2,"Clayton- Adam,The Edge,Bono,Mullen- Larry- Jr",Songs Of Innocence,SONG FOR SOMEONE,03:46
2015-06-16,12:04 AM,Lowden Proud,"Fearing & White, Andy White, Stephen Fearing","White- Andy,Fearing- Stephen",Tea And Confidences,SECRET OF A LONG LASTING LOVE,03:10
2015-06-16,12:07 AM,Columbia,The Wallflowers,"Dylan- Jakob,Irons- Jack,Mathis- Stuart,Richling- Greg,Jaffee- Rami",Glad All Over,REBOOT THE MISSION,03:31
2015-06-16,12:10 AM,Distort Light,Bend Sinister,Moxon- Daniel,"Stories Of Brothers, Tales Of Lovers",JIMMY BROWN,03:48

Both script would output

[akshay@localhost tmp]$ php test.php
Array
(
    [0] => Array
        (
            [date] => 2015-06-16
            [time] => 12:00 AM
            [label] => Island
            [artist] => U2
            [composer] => Clayton- Adam,The Edge,Bono,Mullen- Larry- Jr
            [album] => Songs Of Innocence
            [title] => SONG FOR SOMEONE
            [duration] => 03:46
        )

    [1] => Array
        (
            [date] => 2015-06-16
            [time] => 12:04 AM
            [label] => Lowden Proud
            [artist] => Fearing & White, Andy White, Stephen Fearing
            [composer] => White- Andy,Fearing- Stephen
            [album] => Tea And Confidences
            [title] => SECRET OF A LONG LASTING LOVE
            [duration] => 03:10
        )

    [2] => Array
        (
            [date] => 2015-06-16
            [time] => 12:07 AM
            [label] => Columbia
            [artist] => The Wallflowers
            [composer] => Dylan- Jakob,Irons- Jack,Mathis- Stuart,Richling- Greg,Jaffee- Rami
            [album] => Glad All Over
            [title] => REBOOT THE MISSION
            [duration] => 03:31
        )

    [3] => Array
        (
            [date] => 2015-06-16
            [time] => 12:10 AM
            [label] => Distort Light
            [artist] => Bend Sinister
            [composer] => Moxon- Daniel
            [album] => Stories Of Brothers, Tales Of Lovers
            [title] => JIMMY BROWN
            [duration] => 03:48
        )

)
Akshay Hegde
  • 16,536
  • 2
  • 22
  • 36
  • 1
    This is a very comprehensive answer and is almost perfect except it works on a csv file and not on a csv string as originally requested. I think I can convert it to use str_getcsv instead of fgetcsv so I will mark this as the answer. – BartmanEH Jun 17 '15 at 13:18
  • Yes you can convert like so, otherwise use explode function first use newline char which gives you array of rows then apply explode function on each row which gives array of columns..at present I am on mobile Internet tomorrow morning when I reach office I update answer for string – Akshay Hegde Jun 17 '15 at 18:04
  • 1
    Thanks, @Akshay. I edited my question at the top to show the solution that's working for me. – BartmanEH Jun 18 '15 at 19:36