Value Converter
…s an instanceof Recipe:
Second, for getValueType(), return the internal key of our value type:
doctrine_recipe:
Next is getId()... and we're literally going to return our ID with
$object->getId():
We don't have autocomplete on this, but we know this object will…
Item View Template
…match one piece of config, like
this template, with some other piece of config, like the doctrine_recipe value
type. There are a finite number of these matchers, and we're going to see the most
important ones along the way. So don't worry…
Profiling Command Line scripts
…flush() to, sort of,
"clear" Doctrine's memory of the BigFootSighting object you just finished...
so that it doesn't check it for changes when we call flush() during the next time
through the loop:
The point is: like with everything, make your code do…
App & Test Setup
…who can publish an item under different conditions.
Then we'll do everything custom: add completely custom fields, completely custom API
resources that aren't backed by Doctrine, custom filters and we'll even dive deep
into API Platform's input and output DTO system…
Completely Custom Field via a Data Provider
…providers that
load one object for the item operations.
Normally, we don't need to think about this system because API Platform has a
built-in Doctrine data provider that handles all of it for us. But if we want to
load some extra data…
Custom Item Data Provider
…it extends a less strict
ItemDataProviderInterface. I'm implementing that other crazy interface because
that's what the core Doctrine item data provider uses... and I want to be able
to pass it the same arguments.
Ok: go to the "Code"->"Generate" menu - or…
Setting a Custom Field Via a Listener
…We just set the $isMe field on the authenticated User object. One cool
thing about Doctrine is that if API platform later queries for that same user,
Doctrine will return this exact object in memory, which means that the
$isMe field will be set to…
Adding & Populating the Custom Field
…find the original tab and refresh. Oh! It's not an array
of users! It's a Paginator object with a Doctrine Paginator inside! So... this obviously
isn't an array, but the Paginator object is iterable: we can loop over it
like an array…
Core Listeners & Accessing the "Resource" Objects
…fine... because nobody is the
currently-authenticated user in a console command anyways. But if you did
want a custom field to be populated everywhere - even in a console command - we
have one more solution: a Doctrine postLoad listener. Let's check that out next…
Custom Resource Data Provider
…as the identifier? In Doctrine,
it happens automatically thanks to the @ORM\Id annotation:
When you're not in an entity - or if you want to use a field other than
the database id in an entity - you can add @ApiProperty() with identifier=true:
Cool! Let…
Property Metadata
… 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 property types and more.
What's really…
Collection "Types" and readableLink
…lot of metadata about
each property, like its type and whether it's required. And it gets that from
many different sources like Doctrine metadata and our own PHPDoc.
And because collecting all of this can take time, it caches it. Now,
API Platform is…
Custom Filter, getDescription() & properties
…implement an interface or
extend some base class. In this case, we need to extend AbstractFilter. Make
sure you get the one from Doctrine ORM... it's actually impossible to see which
one we have here... so I'll randomly guess:
Hey! I got it…
Output Properties & Metadata
…that's no surprise! When we serialize a CheeseListing entity, API Platform
can use the Doctrine metadata above the title property to figure out that it's a
string:
But in this case, when it looks at title, it doesn't get any info about…
Custom Filter Logic for Entities
… Our filter
is working!
So this is what it looks like to make a custom filter when your resource is a
Doctrine entity. But the process is different if you need to make a custom filter
for an API resource that is not an entity…
Input Data Transformer
…object. Second, we transform that
CheeseListingInput into a CheeseListing in the data transformer. And
third, the normal Doctrine data persister saves things. That's a really clean
process!
Go back to the docs and look at the put operation that updates cheeses. Will
this work…
Type Validation
…its work, it first tries to figure
out what type the field should be, which we know it does in a number of different
ways, like reading Doctrine metadata, setter argument type-hints and even PHPDoc.
Then, for scalar types like the int price, if…
UUID's
…how do we generate these UUID strings? Symfony 5.2 will come with a
new UUID component, which should allow us to easily generate UUID's and store them
in Doctrine. But since that hasn't been released yet, we can use ramsey/uuid,
which…
UUID as a API Identifier
…talked about it before.
Go to the top of User. Every API Resource needs an identifier. And when you
use Doctrine, API Platform assumes that you want the database id as the identifier.
To tell it to use something different, add @ApiProperty() with identifier=false:
That…
Migrate Password Hashing
…Got it!
It's also kinda fun to see how this looks in the database. Find your terminal
and run:
php bin/console doctrine:query:sql 'SELECT email, password FROM user'
Interesting: every hashed password starts with the same $2y thing. That's no
accident…
x
1000+