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
);

More about JSON Responses

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: POST
  • query: GET
  • cookies: Pretty self-explanatory
  • files: Yea, it's pretty much only request and query that are something different from what they represent
  • server: SERVER
  • headers: 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()
        ];
    }
}