0

To receive my response object from my PHP server I have the code down below. First of all, it works. What does not work is that if my first PHP condition is met, the success function in my Ajax responds correctly but only without using the data object.

This is my AJAX function:

$.ajax({
    type: "PUT",
    url: "http://server/register",
    contentType: "application/json", 
    data: '{"username":"' + username + '", "password":"' + password + '"}',
    success: function(data) {             
        console.log(data)  // The output in my dev tools under Firefox is just a blank line, no error message or even "undefined".           
        console.log("Success") // Works!
        if(data.status == 200){ 
            console.log("Test 1") // Doesn't work. Although status code 200 is shown to me.
        }                       
    },
    error: function(data) {
        console.log(data)   // This works! I can see the content of the object. The correct status code (409) is shown to me.
        if(data.status == 409){
            console.log("Test 2") // Works
        }            
    }
}); 

This is my PHP function:

public function register($request, $response)
{              
    ...

    if(condition-1) {
        echo("Condition 1 works!"); // Works.
        return $response->withStatus(200);                    
    } elseif(condition-2) {
        echo("Condition 2 works!"); // Works too.
        return $response->withStatus(409);            
    }      
}         

I don't see why there is no data object. I'm using the Slim 3 Framework and could probably return a JSON object like this:

$content = ["foo" => 'bar', ...] ; //Any data you wish to return
return $response->withJson($content);

But so far my whole code works without using JSON objects. Even if I var_dump the $response object, I can see that on the server side it is there.

if(condition-1) {
    var_dump($response->withStatus(200)); // Works. I can see it.                
}
Magiranu
  • 299
  • 4
  • 27
  • set the dataType for the ajax request, because even though jQuery docs say it takes an intelligent guess, it's not so intelligent. – Brian Gottier Aug 24 '17 at 21:31
  • read the manual. This is the same answer/question you posted earlier – bassxzero Aug 24 '17 at 21:35
  • @bassxzero Not really in my opinion. I don't need to use JSON as a response object. It works also without, even in my case. But the problem area is only the success function in Ajax. – Magiranu Aug 24 '17 at 21:37
  • "Not really in my opinion." if you understood the problem or framework you wouldn't be posting here – bassxzero Aug 24 '17 at 21:38
  • @bassxzero If you really understand it better than me, why not give me a proper solution without using JSON objects? ;-) – Magiranu Aug 24 '17 at 21:40
  • JSON: JavaScript Object Notation. You want a solution without JSON for a JavaScript script. Makes sense – bassxzero Aug 24 '17 at 21:42
  • If you go to the console, and look at the net tab, what is the actual raw response coming back? – Brian Gottier Aug 24 '17 at 21:45
  • @BrianGottier I only see my echo's. Other than that there is nothing. – Magiranu Aug 24 '17 at 21:50

2 Answers2

4

There's a lot wrong here, so I've done my best to point out what I see wrong, and hopefully with the changes I'm going to suggest you will have success.

If you are trying to use data.status in your ajax success function, then it looks like you think you are returning json, but you aren't. Even if you are, you are corrupting it by echoing "Condition 1 works!".

So think about it, if you have a json response like this:

{'a':'1'}

And you echo something out before it, your response is corrupted, and looks like this:

Condition 1 works!{'a':'1'}

Same corruption occurs if PHP throws an error your way, so be aware of that.

You should also be declaring a dataType for your ajax request, so:

$.ajax({
    type: "PUT",
    url: "http://server/register",
    contentType: "application/json", 
    data: JSON.stringify({
        "username": username, 
        "password": password
    }),
    dataType: 'json', // <-- THIS LINE IS IMPORTANT
    success: function(data, textStatus, jqXHR) {
        // ...
    },
    error: function(jqXHR, textStatus, errorThrown) {
        // ...
    }
});

Note: you were single quoting your data object, so you were doing it the hard way. Just use JSON.stringify on a JS object like I did!

Since my code expects a json response, make sure to look at the other answer here, as it shows how to send back a proper json response with slim.

Finally, in your ajax success function, data.status is not ever going to be available. Docs for jQuery show that there are three parameters, (data, textStatus, jqXHR) and data is specifically for the data, not the HTTP status code or any headers.

I put together a full working example of a mini Slim app. It's fully tested and works (it's just not awesome, so don't laugh):

<?php

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

require 'vendor/autoload.php';

$app = new \Slim\App;

$app->get('/', function (Request $request, Response $response) {
    $response->getBody()->write('<!doctype html>
    <html>
        <head>
            <script
              src="https://code.jquery.com/jquery-3.2.1.min.js"
              integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
              crossorigin="anonymous"></script>
            <script>
                $(document).ready(function(){
                    $("p").on("click", function(){
                        var username = "kookoopapa";
                        var password = "gr3atp4ssWerd";
                        $.ajax({
                            type: "PUT",
                            url: "/register", 
                            data: JSON.stringify({
                                "username": username, 
                                "password": password
                            }),
                            contentType: "application/json", 
                            dataType: "json", // <-- THIS LINE IS IMPORTANT
                            success: function(data, textStatus, jqXHR) {
                                alert( data.a );
                                alert( data.b );
                            },
                            error: function(jqXHR, textStatus, errorThrown) {
                                // ...
                            }
                        });
                    });
                });
            </script>
        </head>
        <body>
            <p>Click</p>
        </body>
    </html>');
    return $response;
});

$app->put('/register', function (Request $request, Response $response) {
    $php_input = file_get_contents('php://input');
    $vars = json_decode( $php_input, TRUE );
    $content = [
        'a' => $vars['username'],
        'b' => $vars['password']
    ];
    return $response->withStatus(200)->withJson($content);
});

$app->run();
Brian Gottier
  • 4,522
  • 3
  • 21
  • 37
  • Thanks for this great explanation. Now, after I modified the Ajax function, I get a `ReferenceError: data is not defined` error. Although under the net tab I see that the JSON is modeled corectly with status code 200. Let me look up tomorrow morning and than I come back. Will mark your post green later on than! – Magiranu Aug 24 '17 at 22:17
  • I'm working on a full example right now because I'm bored. Should have more for you when you come back tomorrow. – Brian Gottier Aug 24 '17 at 22:19
  • Wow, what a thorough example you are providing here! Thanks to that I could now implement many things into my code and got it working. Also you made it more clear to me, how important it is to provide the right return type (dataType) when using Ajax. Again, thanks for all! – Magiranu Aug 25 '17 at 12:17
1

Try to use the following return:

$content = ["foo" => 'bar', ...] ; //Any data you wish to return
return $response->withStatus(200)->withJson($content);
rikardo_paiva
  • 393
  • 1
  • 5