Chapters
36 Chapters
|
3:44:20
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!
Subscribe to download the code!
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "3.1.x-dev", // 3.1.x-dev
"doctrine/annotations": "^2.0", // 2.0.1
"doctrine/doctrine-bundle": "^2.8", // 2.10.2
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.4
"doctrine/orm": "^2.14", // 2.16.1
"nelmio/cors-bundle": "^2.2", // 2.3.1
"nesbot/carbon": "^2.64", // 2.69.0
"phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
"phpstan/phpdoc-parser": "^1.15", // 1.23.1
"symfony/asset": "6.3.*", // v6.3.0
"symfony/console": "6.3.*", // v6.3.2
"symfony/dotenv": "6.3.*", // v6.3.0
"symfony/expression-language": "6.3.*", // v6.3.0
"symfony/flex": "^2", // v2.3.3
"symfony/framework-bundle": "6.3.*", // v6.3.2
"symfony/property-access": "6.3.*", // v6.3.2
"symfony/property-info": "6.3.*", // v6.3.0
"symfony/runtime": "6.3.*", // v6.3.2
"symfony/security-bundle": "6.3.*", // v6.3.3
"symfony/serializer": "6.3.*", // v6.3.3
"symfony/stimulus-bundle": "^2.9", // v2.10.0
"symfony/string": "6.3.*", // v6.3.2
"symfony/twig-bundle": "6.3.*", // v6.3.0
"symfony/ux-react": "^2.6", // v2.10.0
"symfony/ux-vue": "^2.7", // v2.10.0
"symfony/validator": "6.3.*", // v6.3.2
"symfony/webpack-encore-bundle": "^2.0", // v2.0.1
"symfony/yaml": "6.3.*", // v6.3.3
"symfonycasts/micro-mapper": "^0.1.0" // v0.1.1
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.4
"mtdowling/jmespath.php": "^2.6", // 2.6.1
"phpunit/phpunit": "^9.5", // 9.6.11
"symfony/browser-kit": "6.3.*", // v6.3.2
"symfony/css-selector": "6.3.*", // v6.3.2
"symfony/debug-bundle": "6.3.*", // v6.3.2
"symfony/maker-bundle": "^1.48", // v1.50.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/phpunit-bridge": "^6.2", // v6.3.2
"symfony/stopwatch": "6.3.*", // v6.3.0
"symfony/web-profiler-bundle": "6.3.*", // v6.3.2
"zenstruck/browser": "^1.2", // v1.4.0
"zenstruck/foundry": "^1.26" // v1.35.0
}
}
8 Comments
I'm having issues with my PHPStan telling me getStateOptions is from an internal class which it is. I'm using this in my provider where I can reach out for the stateOptions via $operation and $context. However both access the ApiPlatform\Metadata\Metadata class which is an internal one. Is there a different way to reach out for this data?
Hey @Arthur
I think you can access that data through an ApiPlatform state provider.
Here are the docs about them: https://api-platform.com/docs/core/state-providers/
Cheers!
Hey @MolloKhan thanks for reaching out! That's indeed my problem. As stated in the docs I'm implementing the ProviderInterface. However via this class I'm not able to retrieve e.g. the stateoptions because this routes me via the ApiPlatform\Metadata\Metadata class.
So the solution works fine and I have working code. However PHPStan tells me not to use internal classes. Which I ofcourse can ignore. However I'm looking for a neat solution for this :) which perhaps there isn't.
Ohh gotcha, yea... in theory, you should not rely on internal classes, but you could add a couple of tests so they will fail as soon as those classes change in a new version.
It seems the example provided does not work when using Writable Relation Fields with serialization groups.
Trying to create a new object though a relationship throws the dreaded
Unable to generate an IRI for the item of type \"App\\ApiResource\\EntityApi\""error. This seems to only affect Post Operations due to relationships not being properly hydrated during serialization. Get, Get Collection, and Patch all seem to work fine here.For example, Lets say you have two entities: Business - OneToOne - Address. If you were to try create a new business by posting
{ "name":"Little Caesars", "address": { "city": "Detroit" }}to your/api/business/endpoint you would see the following errorUnable to generate an IRI for the item of type \"App\\ApiResource\\AddressApi\"". This is happening because the example in the script does not fully hydrate the DTO before api-platform tries to serialize.Below is a quick and dirty fix that resolved the issue for me on my end.
Hope this helps someone!
Thanks for posting this! This is indeed a problem! I'm fine with your solution! Some other users have pointed out that you can also fix this in the mapper, which I quite like! Here's a description of that approach: https://symfonycasts.com/screencast/api-platform-extending#comment-31551 - if it's unclear let me know, but I think you'll understand the approach.
Cheers!
One issue I came across with the generic/custom
StateProcessoris that not all Entities useid/getId()as their identifier.So in my DTO class, I leveraged the
extraPropertiesarray in the#[ApiResource]to expose that information to theStateProcessor.The upside is that this works! The downside is that I already told ApiPlatform what my resource's ID is in my DTO class in the properties using the
ApiPropertyattribute. But there doesn't seem to be a way to get that information in theprocessmethod of theStateProcessor. Would be nice to not have to add thisextraPropertiesconfig, but hey, this does the trick!Any thoughts about gotchas with this approach?
DTO class
DtoToEntityStateProcessor class
Hey @LCBWeb!
What a cool use of
extraProperties! Well done 👏. But I hear what you mean: this info should already be available. Grabbing the info looks oddly complex. The closest I could find is what's done in this class: https://github.com/api-platform/core/blob/main/src/Api/IdentifiersExtractor.phpIf you poke in there and have success, let me know. Otherwise, it's a tiny bit of duplication, but I think your solution is fine too. And if you only have a few different ids, you could always use a
method_exists()to check for the 2-3 possible getter methods for your id and determine it that way.Cheers!
"Houston: no signs of life"
Start the conversation!