If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeLet's get to work customizing our API. A RESTful API is all about resources. We have one resource - our CheeseListing
- and, by default, API Platform generated 5 endpoints for it. These are called "operations".
Operations are divided into two categories. First, "collection" operations. These are the URLs that don't include {id}
and where the "resource" you're operating on is technically the "collection of cheese listings". For example, you're "getting" the collection or you're "adding" to the collection with POST.
And second - "item" operations. These are the URLs that do have the {id}
part, when you're "operating" on a single cheese listing resource.
The first thing we can customize is which operations we actually want! Above CheeseListing
, inside the annotation, add collectionOperations={}
with "get"
and "post"
inside. Then itemOperations
with {"get", "put", "delete"}
.
... lines 1 - 7 | |
/** | |
* @ApiResource( | |
* collectionOperations={"get", "post"}, | |
* itemOperations={"get", "put", "delete"} | |
* ) | |
... line 13 | |
*/ | |
class CheeseListing | |
... lines 16 - 116 |
A lot of mastering API Platform comes down to learning about what options you can pass inside this annotation. This is basically the default configuration: we want all five operations. So not surprisingly, when we refresh, we see absolutely no changes. But what if we don't want to allow users to delete a cheese listing? Maybe instead, in the future, we'll add a way to "archive" them. Remove "delete"
.
... lines 1 - 7 | |
/** | |
* @ApiResource( | |
... line 10 | |
* itemOperations={"get", "put"} | |
* ) | |
... line 13 | |
*/ | |
... lines 15 - 116 |
As soon as we do that... boom! It's gone from our documentation. Simple, right? Yep! But a bunch of cool things just happened. Remember that, behind the scenes, the Swagger UI is built off of an Open API spec document, which you can see at /api/docs.json
. The reason the "delete" endpoint disappeared from Swagger is that it disappeared from here. API Platform is keeping our "spec" document up to date. If you looked at the JSON-LD spec doc, you'd see the same thing.
And of course, it also completely removed the endpoint - you can see that by running:
php bin/console debug:router
Yep, just GET
, POST
, GET
and PUT
.
Hmm, now that I'm looking at this, I don't love the cheese_listings
part of the URLs... API Platform generates this from the class name. And really, in an API, you shouldn't obsess about how your URLs look - it's just not important, especially - as you'll see - when your API responses include links to other resources. But... we can control this.
Flip back over and add another option: shortName
set to cheeses
.
... lines 1 - 7 | |
/** | |
* @ApiResource( | |
... lines 10 - 11 | |
* shortName="cheeses" | |
... lines 13 - 14 | |
*/ | |
... lines 16 - 117 |
Now run debug:router
again:
php bin/console debug:router
Hey! /api/cheeses
! Much better! And we see the same thing now on our API docs.
Ok: so we can control which operations we want on a resource. And later, we'll learn how to add custom operations. But we can also control quite a lot about the individual operations.
We know that each operation generates a route, and API Platform gives you full control over how that route looks. Check it out: break itemOperations
onto multiple lines. Then, instead of just saying "get"
, we can say "get"={}
and pass this extra configuration.
Try "path"=
set to, I don't know, "/i❤️️cheeses/{id}"
.
... lines 1 - 7 | |
/** | |
* @ApiResource( | |
... line 10 | |
* itemOperations={ | |
* "get"={"path"="/i❤️cheeses/{id}"}, | |
* "put" | |
* }, | |
... line 15 | |
* ) | |
... line 17 | |
*/ | |
... lines 19 - 120 |
Go check out the docs! Ha! That works! What else can you put here? Quite a lot! To start, anything that can be defined on a route, can be added here - like method
, hosts
, etc.
What else? Well, along the way, we'll learn about other, API-Platform-specific stuff that you can put here, like access_control
for security and ways to control the serialization process.
In fact, let's learn about that process right now! How does API Platform transform our CheeseListing
object - with all these private properties - into the JSON that we've been seeing? And when we create a new CheeseListing
, how is it converting our input JSON into a CheeseListing
object?
Understanding the serialization process may be the most important piece to unlocking API Platform.
// composer.json
{
"require": {
"php": "^7.1.3",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/api-pack": "^1.2", // v1.2.0
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/doctrine-migrations-bundle": "^2.0", // v2.0.0
"nesbot/carbon": "^2.17", // 2.19.2
"symfony/console": "4.2.*", // v4.2.9
"symfony/dotenv": "4.2.*", // v4.2.9
"symfony/flex": "^1.1", // v1.9.10
"symfony/framework-bundle": "4.2.*", // v4.2.9
"symfony/yaml": "4.2.*" // v4.2.9
},
"require-dev": {
"symfony/maker-bundle": "^1.11", // v1.11.6
"symfony/profiler-pack": "^1.0" // v1.0.4
}
}