REST APIs - MiguelFieira/AMO-HANDBOEK GitHub Wiki
Disclaimer: In this guide I assume you already know what a REST API is. If not, you should check out this other guide: REST Starter Guide
The JSONResponse Object
The most basic way to create a API-like response is by just returning a JSONResponse Object. No extra bundles required, just make sure you import the right class.
// Don't forget the import UwU <3
use Symfony\Component\HttpFoundation\JsonResponse;
You may be familiar with the way how Symfony renders a page in your Controller methods. By replacing the $this->render() with a JSONResponse(), you return JSON instead of a page.
// Replace the $this->render() with a JSONResponse()
return $this->render('default/index.html.twig', [
'data' => 'ok boomer'
]);
// An example JSONResponse
return new JsonResponse(
[
"status" => "200",
"data" => "My name is Yoshikage Kira. I'm 33 years old."
],
200
);
As you can see the $this->render() and the JSONResponse() look very similar and they are: they both have an array that should contain the data you want to display. The difference is that you don't feed the data to a twig template, but instead the JSONResponse converts all the data in the array to JSON.
Remember the JSONResponse from above? this is what it should output:
{
"status": "200",
"data": "My name is Yoshikage Kira. I'm 33 years old."
}
You don't necessarily have to return a new JSONResponse(), you can create a JSONResponse() earlier in your method and fill it up later with the setData() method.
$response = new JsonResponse();
$response->setData(["data" => 123]);
Of course you can just pass other variables to the JSONResponse() array.
$yoshikage = "Killer Queen Bites the Dust!";
return new JsonResponse(
[
"status" => "200",
"data" => $yoshikage
],
200
);
Responding JSON with a regular Response object
You probably already have Response() imported, so if you don't want the extra import or if you have any other reason to not use JSONResponse(), you can use a regular Response(), which is more commonly used in Symfony. Response() objects should come out of the box with Symfony, if your Symfony does not have a Response() object, you're doing something terribly terribly wrong.
// Don't forget to import the Response if you haven't already
use Symfony\Component\HttpFoundation\Response;
I assume you are already quite familiar with a Response(), so here is an example of a Response() that responds JSON.
$response = new Response();
$response->setContent(json_encode([
"data" => "I, Giorno Giovanna, have a dream.",
]));
$response->headers->set("Content-Type", "application/json");
Requests
What is a REST API if you can't send requests to the API? I tell you, not a very good one.
You know the drill: Make sure you have the right import
// I request you don't mess this up.
use Symfony\Component\HttpFoundation\Request;
Depending on what kind of request data you want to access you'll need to access different Request() attributes, which I'm going to list here and I have shamelessly copied from this page
request: POSTquery: GETcookies: Pretty self-explanatoryfiles: Yea, it's pretty much onlyrequestandquerythat are something different from what they representserver: SERVERheaders: HEADERS
So, if we for example want to see the POST data, we access the request method of the Request() object.
public function api(Request $request) [
// Say, we want to access an id that the client has sent us
$request->request->get('id');
}
A simple example
Ok now you know how all these individual things work, let's put them together.
our request body for our POST request is:
{
"id": 1
}
Here is our example function
public function getName(Request $request) [
$id = $request->request->get('id');
$mouse = $this->getDoctrine()->getManager()->getRepository(Mouse::class)->findOneBy(['id' => $id]);
$name = $mouse->getName();
return new JsonResponse(
[
"mouse_name" => $name
],
200
);
}
which returns:
{
"mouse_name": "Apodemus Erectus"
}
Tip: Responding objects
Perhaps you want to respond an object in your response, but you don't want to pass individual values to your JSONResponse(). You could use the JsonSerializable interface on your Entity class. This way you can json_encode() your entity class directly. You will also need to call the jsonSerialize() method inside your Entity class, inside this method you can specify which data will be returned in the JSON.
class YourAwesomeEntity implements \JsonSerializable {
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $awesomeAttribute;
public function getAwesomeAttribute(): ?string
{
return $this->awesomeAttribute;
}
public function jsonSerialize() {
return [
"attribute" => $this->getAwesomeAttribute()
];
}
}