Slim PHP returning JSON

12,389

Solution 1

Not familiar with slim framework. looks interesting. Sounds like code keeps running after json is displayed. Maybe try exit;ing the php app after responding with your json?

$app->get('/myroute', function() use ($app) {
    // all the good stuff here (getting the data from the db and all that)

    $dataArray = array('id' => $id, 'somethingElse' => $somethingElse);

    $response = $app->response();
    $response['Content-Type'] = 'application/json';
    $response->body(json_encode($dataArray));
    exit();
});
$app->run();

Hope this helps

Solution 2

Try to change body() to write().

I think that this will work: $response->write(json_encode($dataArray));

Solution 3

Slim documentation about returning JSON mentions what you are looking for.

Again from documentations, each route callback accepts three arguments:

Reques
The first argument is a Psr\Http\Message\ServerRequestInterface object that represents the current HTTP request.
Response
The second argument is a Psr\Http\Message\ResponseInterface object that represents the current HTTP response.
Arguments
The third argument is an associative array that contains values for the current route’s named placeholders.

To quote from same page:

If you use a Closure instance as the route callback, the closure’s state is bound to the Container instance. This means you will have access to the DI container instance inside of the Closure via the $this keyword.

So you don't need to uese ($app) when defining a route callback.

Also as mentioned in documentation

Ultimately, each Slim app route MUST return a PSR 7 Response object

To conclude, this should do what you expect:

$app->get('/myroute', function($request, $response, $args) {

// all the good stuff here (getting the data from the db and all that)

$dataArray = array('id' => $id, 'somethingElse' => $somethingElse);

return $response->withJson($dataArray);

});
Share:
12,389
Devin
Author by

Devin

Updated on August 06, 2022

Comments

  • Devin
    Devin over 1 year

    So basically I have my backbone application making an ajax GET call to my slim php app. It expects JSON dataType in return.

    $.ajax({
            url: './myroute',
            type: 'GET',
            dataType: "json",
            data: { username: username, password: password },
            success: function(data) {},
            error: function(data) {}
    });
    

    In my slim file I have:

    $app->get('/myroute', function() use ($app) {
    
        // all the good stuff here (getting the data from the db and all that)
    
        $dataArray = array('id' => $id, 'somethingElse' => $somethingElse);
    
        $response = $app->response();
        $response['Content-Type'] = 'application/json';
        $response->body(json_encode($dataArray));
    
    });
    
        // Tried with these in the above GET request as well:
        // $app->contentType('application/json');
        // echo json_encode($dataArray);
    

    While my request properly goes through (200), and I properly get my JSON data, the error is because it also returns the full index.php page data as well (which my javascript dataType: "json" does not allow, which triggers the error)

    I figured setting the content type to "application/json" would solve this, but it still returns the full page contents as well as the json data.

    Edit for reference

    I used to have it set up so that Slim would render my html like:

    $app->get('/', function () use ($app) {
        // would just have my main page files in home.php instead of index.php
        $app-render('home.php');
    });
    

    So that way there, there was no html page data being returned from index.php. But the way pushState is, I have to have my javascript scripts running on index.php, otherwise my pages wont be loaded properly since when they're requested, the scripts aren't there to delegate where the route should go.

    Any help is appreciated!

    Thanks SO!

  • Devin
    Devin over 11 years
    I didn't place exit(); at the bottom below $app-run(); .. However I did place it directly after my $response->body(); line and it works like a charm! Thank you sir!
  • Devin
    Devin over 11 years
    If you make the answer reflect what worked for me, I'll check you off!
  • remarsh
    remarsh over 9 years
    This assumes a 200. It would be better to include the respective HTTP response code for additional context.
  • Nima
    Nima about 6 years
    Not a good idea to exit(), a route callback MUST return a response object. Slim has some methods for creating a JSON response but if you want to write something to response body, you should return the response object in the end.
  • vortextangent
    vortextangent almost 4 years
    @Nima You are probably right, a return $response would have probably been a better solution.