2

So here is the issue. I am pulling a CSV file from an API and need to place it into an array. Here is my current code:

$url = "https://www.*****************";
$myvars = 'username=*********&password=*************';

$ch = curl_init( $url );
curl_setopt( $ch, CURLOPT_POST, 1);
curl_setopt( $ch, CURLOPT_POSTFIELDS, $myvars);
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
//curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text'));
curl_setopt( $ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($ch, CURLOPT_VERBOSE, true); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

if(!curl_exec($ch)){
    die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
} else {
    $response = curl_exec($ch);
    $exploded = nl2br($response);   
    //echo $response."<br>";
    var_dump($exploded);
}
curl_close($ch);

The problem is I am getting the response:

string(245) ""Number","Name","Description","Type","Fixed Width Boolean","Quote Character","Delimiter Character","End of Line Sequence","Header Boolean","Column Count" "1","All Calls","All Call Data","Call","false","None",",","\r\n","true","14" "

This is two lines in the CSV, but comes out in a single string line. I tried exploding it, but it seems to have two delimiters and I tried splitting it, but it will not find the second delimiter. I want it to generate like this:

array(
"Number" => 1,
"Name" => "All Calls",
"Description" => "All Call Data",
"Type" => "Call",
"Fixed Width Boolean" => false,
"Quote Character" => "None",
"Delimiter Character" => ",",
"End of Line Sequence" => "\r\n",
"Header Boolean" => true,
"Column Count" => 14
);

The first line of the CSV is the headers and the data underneath is the data it needs to align to. Also future requests will have multiple lines of data and they need to match with the headers too. Any ideas?

5
  • So you tried exploding like this? $exploded = explode(",", $response); Commented Dec 3, 2015 at 23:15
  • You should show the contents of the file using code formatting. Also, no need to show output from var_dump(), just show a few lines from the file itself. Commented Dec 3, 2015 at 23:26
  • Unrelated to your problem but you are executing the http request twice with your two curl_exec calls. Commented Dec 4, 2015 at 0:12
  • You are right I was executing it twice. Fixed that. Commented Dec 4, 2015 at 14:33
  • Yes the first thought was just to explode on the "," but since there is a break in the string here: "Column Count" "1" I need to somehow get it to start a new line or array. Commented Dec 4, 2015 at 15:03

3 Answers 3

2

If you're dealing with CSV, try using the built-in function for such. Then use array_combine to stick your headers in as keys:

$response = curl_exec($ch);
$csv_data = array_map('str_getcsv', explode("\n", $response));
$headers = array_shift($csv_data);
foreach ($csv_data as $v) {
    $data[] = array_combine($headers, $v);
}

As an example:

$response = <<< CSV
"Number","Name","Description","Type","Fixed Width Boolean","Quote Character","Delimiter Character","End of Line Sequence","Header Boolean","Column Count"
"1","All Calls","All Call Data","Call","false","None",",","\\r\\n","true","14"
CSV;
$csv_data = array_map('str_getcsv', explode("\n", $response));
$headers = array_shift($csv_data);
foreach ($csv_data as $v) {
    $data[] = array_combine($headers, $v);
}
print_r($data);

Output:

Array
(
    [0] => Array
        (
            [Number] => 1
            [Name] => All Calls
            [Description] => All Call Data
            [Type] => Call
            [Fixed Width Boolean] => false
            [Quote Character] => None
            [Delimiter Character] => ,
            [End of Line Sequence] => \r\n
            [Header Boolean] => true
            [Column Count] => 14
        )

)
Sign up to request clarification or add additional context in comments.

1 Comment

If you edit your question to include 10 lines from your file, as requested in comments, you'll get much better advice.
1

You can also turn your csv string into a file pointer and use fgetcsv on it. Here is an example of how it works:

Josh:~$ php -a
Interactive shell

php > $data = <<<CSV
<<< > "col1","col2"
<<< > "d1",","
<<< > CSV;
php > echo $data;
"col1","col2"
"d1",","
php > $fp = fopen('data://text/plain,' . $data, 'r');
php > while (($row = fgetcsv($fp)) !== false) {
php {   var_dump($row);
php { }
array(2) {
  [0]=>
  string(4) "col1"
  [1]=>
  string(4) "col2"
}
array(2) {
  [0]=>
  string(2) "d1"
  [1]=>
  string(1) ","
}

Using your example it would be similar to the following

$response = <<<CSV
"Number","Name","Description","Type","Fixed Width Boolean","Quote Character","Delimiter Character","End of Line Sequence","Header Boolean","Column Count"
"1","All Calls","All Call Data","Call","false","None",",","\r\n","true","14"
CSV;
$fp = fopen('data://text/plain,' . $response, 'r');
$data = [];
$header = fgetcsv($fp); // first row is column headers
while (($row = fgetcsv($fp)) !== false) {
    $data[] = array_combine($header, $row);
}
print_r($data); // list of rows with keys set to column names from $header
/*
Array
(
    [0] => Array
        (
            [Number] => 1
            [Name] => All Calls
            [Description] => All Call Data
            [Type] => Call
            [Fixed Width Boolean] => false
            [Quote Character] => None
            [Delimiter Character] => ,
            [End of Line Sequence] =>

            [Header Boolean] => true
            [Column Count] => 14
        )

)
*/

3 Comments

I thought I had the answer but yours is perfect. Thanks a ton. I have been stuck on this for 3 days.
You're welcome. I've been using the data:// + fgetcsv trick when I got sick of failing to parse them myself.
Can I get a +1 for the question? LOL? This was a learning experience. I have been coding for a long time but I hate doing curl requests because response data is always just so inconsistant.
-2

Well, this is a bit "hacky" but it works....

PHP Fiddle

 $response = '"Number","Name","Description","Type","Fixed Width Boolean","Quote Character","Delimiter Character","End of Line Sequence","Header Boolean","Column Count","1","All Calls","All Call Data","Call","false","None",",","\r\n","true","14"'; 

 $response = preg_replace('/[,]/', "*", $response);
 $response = str_replace('*"*"*', '*","*', $response);

 $exploded = explode("*", $response);

 $count = count($exploded)/2;

 $newArray = [];

 for($i=0; $i<$count; ++$i){
     $newArray[$exploded[$i]] = $exploded[$i+$count];
 }

 print_r($newArray);

Which prints

 Array
 (
     ["Number"] => "1"
     ["Name"] => "All Calls"
     ["Description"] => "All Call Data"
     ["Type"] => "Call"
     ["Fixed Width Boolean"] => "false"
     ["Quote Character"] => "None"
     ["Delimiter Character"] => ","
     ["End of Line Sequence"] => "\r\n"
     ["Header Boolean"] => "true"
     ["Column Count"] => "14"
 )

4 Comments

Do not parse csv this way. Use the built in fgetcsv or str_getcsv as needed.
@JoshJ Don't down vote an answer that works...I can parse a csv anyway I would like really. I even said it was a bit "hacky"...geeez.
That's the way the forums are supposed to work. Vote up the best practices, vote down bad ideas. Nothing personal. I'm sure you know your stuff and provide a lot of help around here.
@JoshJ Actually, when you downvote, it should be if "This answer is not useful" but my answer is. Not elegant, but it works, therefore can be useful :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.