gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
API Platform works by taking a class like DragonTreasure
and saying that you want
to expose it as a resource in your API. We do that by adding the ApiResource
attribute. Right now, we're putting this above a Doctrine entity, though, in a future
tutorial, we'll learn that you can really put ApiResource
above any class.
Out-of-the-box, every ApiResource
includes 6 endpoints, which API Platform calls
operations. You can actually see these in the profiler. This is the profiler for
GET /api/dragon_treasures.json
. Click on the "API Platform" section. On top,
we see metadata for this API resource. Below, we see the operations. This... is
more info than we need right now, but there's Get
, GetCollection
, Post
,
Put
, Patch
and finally Delete
. These are the same things we see on the
Swagger documentation.
Let's take a quick look at these. First, which operations return data? Actually,
all of them - except for Delete
. This Get
, the Post
, Put
and Patch
endpoints all return a single resource - so a single treasure. And
GET /api/dragon_treasures
returns a collection.
Which endpoints do we send data to when we use them? That's POST
to create,
and PUT
and PATCH
to update. We don't send any data for DELETE
or either
GET
operation.
Most of the endpoints are pretty self-explanatory: get a collection of treasures,
a single treasure, create a treasure and delete a treasure. The only confusing ones
are put versus patch. PUT
says "replaces" and PATCH
says "updates". That...
sounds like two ways of saying the same thing!
The topic of PUT versus PATCH in APIs can get spicy. But in API Platform, at least today, PUT and PATCH work the same: they're both used to update a resource. And we'll see them in action along the way.
One of the things that you might want to do is customize or remove some of these operations... or even add more operations. How could we do that? As we saw on the profiler, each operation is backed by a class.
Back over above the DragonTreasure
class, after description
, add an operations
key. Notice that I'm getting auto-completion for the options because these are
named arguments to the constructor of the ApiResource
class. I'll show you that
in a minute.
Set this to an array and then repeat every operation we currently have. So,
new Get()
, hit tab to auto-complete that, GetCollection
, Post
, Put
, Patch
and Delete
.
Now, if we move over to the Swagger documentation and refresh... absolutely nothing
changes! That's what we wanted. We've just repeated exactly the default
configuration. But now we're free to customize things. For example, suppose we
don't want treasures to be deleted... because a dragon would never allow their
treasure to be stolen. Remove Delete
.. and I'll even remove the use
statement.
Now when we refresh, the DELETE
operation is gone.
Ok, so every attribute we use is actually a class. And knowing that is powerful.
Hold command or control and click on ApiResource
to open it. This is really cool.
Every argument to the constructor is an option that we can pass to the attribute.
And almost all of these have a link to the documentation where you can read more.
We'll talk about the most important items, but this is a great resource to know about.
One argument is called shortName
. If you look over at Swagger,
our "model" is currently known as DragonTreasure
, which obviously matches the
class. This is called the "short name". And by default, the URLs -
/api/dragon_treasures
- are generated from that.
Let's say that we instead want to shorten all of this to just "treasure". No
problem: set shortName
to Treasure
.
As soon as we do that, watch the name and URLs. Nice. This resource is now known as "Treasure" and the URLs updated to reflect that.
Though, that's not the only way to configure the URLs. Just like with ApiResource
,
each operation is also a class. Hold Command (or Ctrl) and Click to
open up the Get
class. Once again, these constructor arguments are options...
and most have documentation.
One important argument is uriTemplate
. Yup, we can control what the
URL looks like on an operation by operation basis.
Check it out. Remember, Get
is how you fetch a single resource. Add
uriTemplate
set to /dragon-plunder/{id}
where that last part will be the placeholder
for the dynamic id. For GetCollection
, let's also pass uriTemplate
set to /dragon-plunder
.
Ok! Let's go check the docs! Beautiful! The other operations keep the old URL,
but those use the new style. Later, when we talk about subresources, we'll go
deeper into uriTemplate
and its sister option uriVariables
.
Ok... since it's a bit silly to have two operations with weird URLs, let's remove that customization.
Now that we know a bunch about ApiResource
and these operations, it's time
to talk about the heart of API Platform: Symfony's serializer. That's next.
Hey Stiff!
Hmm, well that's no fun :/. First, are you sure that the 405 Method not allowed is coming from Nginx? I mean, it probably is, but it could also, in theory, be coming from something like CloudFlare (if it is, it should be pretty obvious on that page) or Symfony itself (if it is, you would likely be seeing either your custom exception page or the generic "Symfony error page" for production).
Assuming that it IS coming from nginx, I'm familiar with Fastpanel or how much control it gives you over the raw nginx config. What have you tried so far?
Cheers!
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^3.0", // v3.0.8
"doctrine/annotations": "^1.0", // 1.14.2
"doctrine/doctrine-bundle": "^2.8", // 2.8.0
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
"doctrine/orm": "^2.14", // 2.14.0
"nelmio/cors-bundle": "^2.2", // 2.2.0
"nesbot/carbon": "^2.64", // 2.64.1
"phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
"phpstan/phpdoc-parser": "^1.15", // 1.15.3
"symfony/asset": "6.2.*", // v6.2.0
"symfony/console": "6.2.*", // v6.2.3
"symfony/dotenv": "6.2.*", // v6.2.0
"symfony/expression-language": "6.2.*", // v6.2.2
"symfony/flex": "^2", // v2.2.4
"symfony/framework-bundle": "6.2.*", // v6.2.3
"symfony/property-access": "6.2.*", // v6.2.3
"symfony/property-info": "6.2.*", // v6.2.3
"symfony/runtime": "6.2.*", // v6.2.0
"symfony/security-bundle": "6.2.*", // v6.2.3
"symfony/serializer": "6.2.*", // v6.2.3
"symfony/twig-bundle": "6.2.*", // v6.2.3
"symfony/ux-react": "^2.6", // v2.6.1
"symfony/validator": "6.2.*", // v6.2.3
"symfony/webpack-encore-bundle": "^1.16", // v1.16.0
"symfony/yaml": "6.2.*" // v6.2.2
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
"symfony/debug-bundle": "6.2.*", // v6.2.1
"symfony/maker-bundle": "^1.48", // v1.48.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/stopwatch": "6.2.*", // v6.2.0
"symfony/web-profiler-bundle": "6.2.*", // v6.2.4
"zenstruck/foundry": "^1.26" // v1.26.0
}
}
Hi Ryan,
I am unable to execute PUT/PATCH operations on my server (Error 405 Method not allowed). I am using Fastpanel where Nginx is running for the frontend. Tried some fixes from the internet but that didn't help. Any help would be really appreciated.
Best regards,
Stiff