1

I'm trying to POST to a PHP controller using jQuery Ajax. I then want my controller to retrieve data from an API and return the data to my AJAX function.

Here is my javascript:

$(function() {

    $.ajax({
        type: 'POST',
        url: '/mycontroller/myaction/',
        success: function(data) {       
            console.log(data);
        }
    });

});

Here is my action in my controller:

public function myaction() {

    $ch = curl_init();

    $endPoint = 'https://endpointfortheapi.com';

    curl_setopt($ch, CURLOPT_URL, $endPoint); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-type: application/json; charset=utf-8'
    ));

    $response = curl_exec($ch);

    $response = json_encode($response);

    echo $response;

    curl_close($ch);
}

This seems to work, however, when I use json_encode() the array is returned as an escaped string, not a json object. When I console.log(data) in my AJAX request, I see a string like this:

"[{\"firstProperty\":\"firstValue\",\"secondProperty\":\"secondValue\"}]"

How can I encode the response array to be an actual JSON object?

Michael Lynch
  • 2,198
  • 3
  • 19
  • 41

2 Answers2

1

So you’re doing this:

$response = curl_exec($ch);    
$response = json_encode($response);

Unclear what the returned data is from https://endpointfortheapi.com, but it seems to me that you are taking a source JSON response & then double-encoding the response when you do json_encode again.

If you send a plain string to json_encode instead of an object or array—it will just escape it exactly as you are seeing. So I would just remove or comment out that line & see if that clears things up.

Also, you should be setting proper JSON headers in your PHP before the echo. So based on what I mention above & the headers I would refactor your PHP code to be like this:

public function myaction() {

    $ch = curl_init();

    $endPoint = 'https://endpointfortheapi.com';

    curl_setopt($ch, CURLOPT_URL, $endPoint); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    $response = curl_exec($ch);
    // $response = json_encode($response);

    // header('X-JSON: (' . $response. ')');
    header('Content-type: application/json');
    echo $response;

    curl_close($ch);

}

I commented out the X-JSON header since there is some controversy surrounding the use of that custom header which is used by some applications to automatically evaluate JSON data if they are using the Prototype JavaScript framework. Not worth the hassle if you are not using Prototype and don’t care about such things.

Giacomo1968
  • 23,903
  • 10
  • 59
  • 92
  • 1
    I'm intrigued by that `X-JSON` header in there; what's the advantage of echoing the content twice like that, and isn't there a risk of it creating a broken HTTP response? – IMSoP Jun 27 '14 at 18:20
  • 1
    Also, the correct content type for JSON is `application/json`, no `x-` http://stackoverflow.com/q/477816/157957 – IMSoP Jun 27 '14 at 18:24
  • @IMSoP I have been out of serious JavaScript development for about 5+ years so it seems like `X-JSON` is not encouraged anymore. And ditto with my `application/x-json`. Commented out the `X-JSON` and amended my answer to address the issue as well as set `application/json`. But the core issue here is the double-enclosing of the response JSON in the original poster’s code; get rid of that and all is good. – Giacomo1968 Jun 27 '14 at 18:29
  • @JakeGould Thanks for your help. I believe the data that is being returned from the API I'm using is an array. I'm under the impression that `json_decode()` converts an array to a JSON object. I'm setting my headers using `CURLOPT_HTTPHEADER`. I just didn't include it in my question. – Michael Lynch Jun 27 '14 at 18:37
  • @MichaelLynch “I believe the data that is being returned from the API I'm using is an array.” A pure array? Not JSON or XML? How would that work? “ I'm under the impression that `json_decode()` converts an array to a JSON object.” JSON decode decodes JSON into an object or array. Do yourself a favor. Just do an `echo $response;` to see what the returned data format is. 100% positive it is already JSON so no need to double encode it. – Giacomo1968 Jun 27 '14 at 18:43
  • 1
    @JakeGould Yes. You are right. The response is not an actual array. My mistake. It is an array returned as a string. Removing `json_encode()` fixed my issue. I also required `dataType: json` in my Ajax request. Out of curiosity, what is the difference between setting the headers using `header()` and setting the headers using `CURLOPT_HTTPHEADER` as I do my question above. Also, wouldn't `header()` need to be before `curl_exec`? – Michael Lynch Jun 27 '14 at 18:47
  • @MichaelLynch `CURLOPT_HTTPHEADER` only has to do with the cURL request in your code. It is setting cURL header options. The `header()` I am setting is connected to your `echo`ing of content. The `header()` preceded the `echo` so as to tell the recipient of the data what that `echo` is. Placement of everything here is 100% good in my refactoring. You are getting data from one place with `curl` and then `echo`ing that received data to another place afterwards. Two different things. – Giacomo1968 Jun 27 '14 at 18:55
-1

Set the dataType to json in your ajax request:

$(function() {

$.ajax({
    type: 'POST',
    url: '/mycontroller/myaction/',
    dataType: 'json',
    success: function(data) {       
        console.log(data);
    }
});

});
cOle2
  • 4,116
  • 1
  • 20
  • 23
  • Pretty sure the issue here is the PHP side of things & not the JavaScript AJAX call. So setting the `dataType` to `json` doesn’t hurt, but won’t solve the issue. – Giacomo1968 Jun 27 '14 at 18:20
  • Setting the `dataType` will turn a json string into a json object. The OP will most likely need this even if there are other errors in his code. – cOle2 Jun 27 '14 at 18:34
  • 1
    @oOle2 @JakeGould Adding `dataType` to my Ajax request and removing `json_encode()` fixed my issue. Thanks guys! – Michael Lynch Jun 27 '14 at 18:43