I am using the Slim framework with PHP to create a RESTful API for my app. However, I assumed that the framework would have some way of creating easier JSON outputs rather than just exit($jsonEncodedVariable);
.
Am I missing some开发者_JS百科thing in the framework, or do I need to use json_encode()
... exit($json)
... for every method?
All of the data is taken out of the my MySQL database and would then be put into a JSON array depending on what REST request was called.
For example, if /api/posts/all
was requested, I would exit()
a JSON array of all the posts which each value for its own key, "value" : key
.
My question is, is there an easy way, using the slim framework, for exit()
'ing JSON code instead of exiting it as plain text?
Why not just use Slim's Response Object? (also... why exit?)
$dataAry = // Some data array
$response = $app->response();
$response['Content-Type'] = 'application/json';
$response['X-Powered-By'] = 'Potato Energy';
$response->status(200);
// etc.
$response->body(json_encode($dataAry));
// Or echo json_encode($dataAry)
Let me preface by saying I still consider myself a noob so if I'm making errors please correct me so I can learn. But, I was playing with a similar problem/question and I thought I might chime in with 2 cents and archive a little more discussion on the matter. The more information there is about Slim on Stack the better.
I was basically toying with the same thing and I noticed that you were using exit; At first, I was using exit also because echo was including a bunch of HTML and mucking up what was being returned to my AJAX call. When I used exit, it cleanly cut the HTML out but then the Slim response object wasn't changing the response headers as I defined (see above code.)
What I realized was that this isn't how Slim was designed to work. Use echo, not exit. NOTE - Slim Doc:
Whenever you echo() content from within a route callback, the echo()’d content is captured >in an output buffer and later appended to the Response body before the HTTP response is >returned to the client.
That's convenient, but I was not able to echo. What I was messing up on was a bigger problem. Separation of content from behavior. If you're like me, you're setting up a single page application where this code basically sits on index.php. There is initial html that I needed to load up so I included it on that page. What I needed to do was create a cleaner separation. My routing was properly set up and so when people GET '/' the Slim_Views (see Develop Rel.) returns a rendered template of html and js for me. Brilliant!
Now I have all of Slim's tools at disposal and my code is much much cleaner, separate, manageable, and more compliant with http protocols. I guess this is what frameworks are for. :-)
NOTE: I'm not saying all this is what went down on your end, but I thought the question and your setup seemed very similar. It might help another new guy who wanders down this same path.
UPDATE: As @alttag mentions, this answer is getting out of date (Slim 2)
For Slim3, see an answer below or see this page in the documentation
header("Content-Type: application/json");
echo json_encode($result);
exit;
Hint: Using The Slim PHP Framework for Developing REST APIs
Using Slim 3, I'm using this format:
<?php
$app = new \Slim\App();
$app->get('/{id}', function ($request, $response, $args) {
$id = $request->getAttribute('id');
return $response->withJSON(
['id' => $id],
200,
JSON_UNESCAPED_UNICODE
);
});
On request "/123", result JSON with:
{
id: "123"
}
More infos read here.
[UPDATE]
Added second and third param to withJSON
. Second is The HTTP status code, and third is Json encoding options (best for especial chars and others, for example: print "ã" correctly)
you can extend slim with an output function which output is depending the REST request was called:
class mySlim extends Slim\Slim {
function outputArray($data) {
switch($this->request->headers->get('Accept')) {
case 'application/json':
default:
$this->response->headers->set('Content-Type', 'application/json');
echo json_encode($data);
}
}
}
$app = new mySlim();
and use it like this:
$app->get('/test/', function() use ($app) {
$data = array(1,2,3,4);
$app->outputArray($data);
});
Since everyone has complicated their answers with functions and classes, I'll throw in this simplified answer. The \Slim\Http\Response can do it for you like this:
$app = new \Slim\Slim();
$app->get('/something', function () use ($app) {
$response = $app->response();
$response['Content-Type'] = 'application/json';
$response->status(200);
$response->body(json_encode(['data' => []]));
});
$app->run();
As you're most likely only returning JSON data it might be a good idea to make an appropriate middleware, see http://www.sitepoint.com/best-practices-rest-api-scratch-introduction/.
I think Slim also provides a middleware object which does this automatically so users of that framework doesnt have to write json_decode and encode on every request, its called the
Slim_Middleware_ContentType
object.
$app->response()->('application/json');
$app->add(new Slim_Middleware_ContentType());
it does the decoding for you. the decoding works great.But for encoding the last post is great.
Thanks, Dharani
I feel your pain. I wanted to make a reusable function, so I made a helpers file, and included this:
function toJSON($app, $content) {
$response = $app->response;
$response['Content-Type'] = 'application/json';
$response->body( json_encode($content) );
};
And then I used it like this:
$app->get('/v1/users/:id', function($id) use ($app)
{
//instantiate SMM data model
$model = new user_model($site);
//get all docs, or one, depending on if query contains a page ID
$doc = $model->get(array());
//if the object contains main -- we don't need the outer data.
toJSON($app, $doc);
});
Edit: I think it would be really nice if there were already functions like this built into the response object for the popular mime types
//JSON output in slim3
$app->get('/users', function($request,$response,$args) {
require 'db_connect.php';
$stmt = $pdo->query("SELECT * FROM users");
$result=$stmt->fetchAll(PDO::FETCH_ASSOC);
if ($stmt->rowCount() > 0) {
return $response->withStatus(200)
->withHeader('Content-Type', 'application/json')
->write(json_encode($result));
}
else{
$result = array(
"status" => "false",
"message" => "Result not found"
);
return $response->withStatus(200)
->withHeader('Content-Type', 'application/json')
->write(json_encode($result));
}
});
function _die($array){
echo json_encode($array);
exit;
}
$result = mysql_query("SELECT * FROM table");
while($row = mysql_fetch_assoc($result)){
$array[] = $row;
}
_die($array);
why not $response->write(json_encode($dataAry));
instead of echo json_encode($dataAry);
?
My fix was adding "exit;" at the end of the json print out, my dev server didn't care, but my live server would not trigger the json end event. I did not need to add headers or use json_encode.
Use Slim JSON API https://coderwall.com/p/otcphg/create-a-json-restfull-api-using-slim-framework. You can handle JSON output with it.
[BEFORE]: Content-Type text/html; charset=UTF-8
Not working with SOAPUI JSON :(
$this->get('get_all', function ($req, $res, $args) {
$um = new UserModel();
return $res
->withHeader('Content-Type', 'application/json')
->getBody()
->write(
json_encode(
$um->get_all()
)
);
});
[AFTER]: Content-Type application/json;charset=utf-8
Working with SOAPUI JSON ;)
$this->get('get_all', function ($req, $res, $args) {
$um = new UserModel();
return $res
->withHeader('Content-type', 'application/json;charset=utf-8')
->withJson($um->get_all());
You can use in slim3, Slim’s Response object custom method withJson($data, $status, $encodingOptions)
$app->get('/hello/{name}', function ($request, $response, $args) {
$data['msg']='Hello '.$request->getAttribute('name');
$newResponse = $response->withJson($data);
});
For more information read here.
This is how I do it in slim version 2
$app->response->headers->set("Content-Type", 'application/json');
return $app->response->write(json_encode([
'status' => true,
'message' => 'Your message'
]));
I use https://github.com/entomb/slim-json-api for my API written in Slim 2 to enable JSON-response. Init code looks something like this:
function APIRequests () {
$app = \Slim\Slim::getInstance();
$app->view(new \JsonApiView());
$app->add(new \JsonApiMiddleware());
}
$app->group('/api', 'APIRequests', function () use ($app) {
$app->get('/areas/:id', function ($id) use ($app) {
$app->render(200, Area::find($id));
});
});
I really like the abstraction level using middleware and grouping of routes, making it easy to apply different response types to different areas of the app.
header("Content-Type : application/json"); echo json_encode($data);
精彩评论