Normalizer Decoration & "Normalizer Aware"
…for normalizing ApiResource objects into
JSON-LD. This is another spot where you can rely on the documentation to give you
the exact service ID you need. It's api_platform.jsonld.normalizer.item:
Try the test again: testOwnerCanSeeIsPublishedField
Yes! We see our dump! And..…
Dynamic Groups: Context Builder
…honestly, just to learn more about how
API Platform works under the hood - I want to show you an alternative solution.
Remove the ApiProperty attribute:
And replace it with two new groups. We're not going to use the normal
treasure:read and treasure:write…
Simpler State Processor
…Step 3 is to tell API Platform when to use this processor. In DragonTreasure, we
want this to be used for both our Post and Patch operations. Set
processor to DragonTreasureStateProcessor::class... and repeat that down for
Patch.
Done! API Platform will call our processor…
Calling the Controller & View Event
…model". Then, you could write a listener
to this event that transforms that Article entity into HTML by rendering the template.
This event isn't used anywhere in Symfony's core, but it is used extensively
inside API Platform. Internally, their controllers return objects. Then…
DTO & Security
…
And the full flow here is fascinating! When we make a patch() request
to a treasure, API Platform starts by using our data provider to find the
DragonTreasure entity. Then we map that to a DragonTreasureApi object. Next,
the new value is deserialized onto that…
Entities, DTO's & The "Central" Object
…this entityClass solution.
The reason... is a bit technical, but important.
Internally, for every API request, API Platform has a central object that it's
working on. If we fetch a single item, that central object is that single
item. And that's really important…
Triggering a "Publish"
…We've
completely converted this complex API resource to our DTO-powered system!
High five!
Next: Let's make it possible to write the $owner property on dragon treasure.
This involves a trick that will help us better understand how API Platform
loads relation data.
DTO -> Entity State Processor
…default processor when using stateOptions. But... because our
UserApi isn't an entity, PersistProcessor does nothing. Finally,
API Platform serializes the UserApi back into JSON... but without the id
populated, it fails to generate the IRI.
Watch! Over in UserApi, temporarily default $id to 5…
Provider: Transforming Entities to DTOs
…Pagination object. Now that we're
just returning an array, it makes API Platform think that we don't support
pagination.
The solution is dead-simple. Instead of returning $dtos,
return new TraversablePaginator() with a new \ArrayIterator() of $dtos.
For the other arguments, we can…
Creating the User Entity
…gorgeous new Doctrine entity... but as far as API Platform
is concerned, we still only have one API resource: CheeseListing.
Next: let's expose User as an API Resource and use all of our new knowledge to
perfect that new resource in... about 5 minutes.
Resetting the Database Between Tests
…how can we empty the database before each test? There are a few answers,
but one common one you'll see in the API Platform world is called Alice. Find
your terminal and install it with:
composer require "alice:^2.7" --dev
This will install…
FrameworkBundle Recipe Part 2: The Kernel Class
…adopted by most browsers. We talk more about it inside our
API Platform Security
tutorial - but this setting shouldn't cause problems in most setups and is
definitely more secure.
So let's say "y" for all of these changes.
Keep going! Now we're…
Bootstrapping a Test Suite
…database:create. But since we
want this command to execute in the test environment, also add --env=test:
Repeat that same thing with the doctrine:schema:create command:
Perfect! Next, Api Platform has some really nice testing tools which... aren't
released yet. Boo! Well... because…
ACL: Only Owners can PUT a CheeseListing
…Ok, let's fix this!
The access_control option - which will probably be renamed to security in
API Platform 2.5 - allows you to write an "expression" inside using Symfony's
expression language. This is_granted() thing is a function that's available
in that…
Property Metadata
…types of each field. Are these strings? Integers?
Aliens?
API Platform gets metadata about each property from many different places, like
by reading Doctrine metadata, PHPDoc, looking at the return types of getter methods,
looking at the argument type-hint on setters, PHP 7.4…
Pagination Context
…query parameter that's used for pagination
can be changed - it doesn't need to be ?page=.
My point is: we don't need to hardcode the max per page or read the page query
parameter directly because API Platform already has this info! Where…
Filter Class Arguments
…Ah, error!
Class DailyStatsDateFilter does not have argument $throwOnInvalid
API platform does a cool, but kind of strange thing: if you pass an arguments
option to a filter, it tries to pass that argument - by name - to the
constructor of your filter.
Check it out…
Input Data Transformer
…A 201 status code. It worked!
So using a DTO input is a 3-step process. First, API Platform deserializes
the JSON we send into a CheeseListingInput object. Second, we transform that
CheeseListingInput into a CheeseListing in the data transformer. And
third, the normal Doctrine…
Input DTO Validation
…To do that, we need the validator! Add a public function
__construct() with a ValidatorInterface argument. But grab the one
from ApiPlatform\, not Symfony\. I'll explain why in a second. Call that
argument $validator and then I'll go to Alt+Enter and select…
UUID's
…Ramsey\ - then call uuid4(), which is how you get a random UUID string:
Run the tests again:
Now they're happy!
Next, the UUID is not part of our API at all yet. Let's tell API Platform
to start using it as the identifier.
x
1000+