Chapters
48 Chapters
|
5:13:28
|
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!
35.
DTO Quirks: Embedded Objects
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.
This tutorial also works great with API Platform 2.6.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"api-platform/core": "^2.1", // v2.5.10
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/annotations": "^1.0", // 1.12.1
"doctrine/doctrine-bundle": "^2.0", // 2.1.2
"doctrine/doctrine-migrations-bundle": "^3.0", // 3.0.2
"doctrine/orm": "^2.4.5", // 2.8.2
"nelmio/cors-bundle": "^2.1", // 2.1.0
"nesbot/carbon": "^2.17", // 2.39.1
"phpdocumentor/reflection-docblock": "^3.0 || ^4.0 || ^5.0", // 5.2.2
"ramsey/uuid-doctrine": "^1.6", // 1.6.0
"symfony/asset": "5.1.*", // v5.1.5
"symfony/console": "5.1.*", // v5.1.5
"symfony/debug-bundle": "5.1.*", // v5.1.5
"symfony/dotenv": "5.1.*", // v5.1.5
"symfony/expression-language": "5.1.*", // v5.1.5
"symfony/flex": "^1.1", // v1.21.6
"symfony/framework-bundle": "5.1.*", // v5.1.5
"symfony/http-client": "5.1.*", // v5.1.5
"symfony/monolog-bundle": "^3.4", // v3.5.0
"symfony/security-bundle": "5.1.*", // v5.1.5
"symfony/twig-bundle": "5.1.*", // v5.1.5
"symfony/validator": "5.1.*", // v5.1.5
"symfony/webpack-encore-bundle": "^1.6", // v1.8.0
"symfony/yaml": "5.1.*" // v5.1.5
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.3", // 3.3.2
"symfony/browser-kit": "5.1.*", // v5.1.5
"symfony/css-selector": "5.1.*", // v5.1.5
"symfony/maker-bundle": "^1.11", // v1.23.0
"symfony/phpunit-bridge": "5.1.*", // v5.1.5
"symfony/stopwatch": "5.1.*", // v5.1.5
"symfony/twig-bundle": "5.1.*", // v5.1.5
"symfony/web-profiler-bundle": "5.1.*", // v5.1.5
"zenstruck/foundry": "^1.1" // v1.8.0
}
}
12 Comments
Hmmm... I am a bit underwhelmed by DTO so far.
At least with the example provided in this course.
Interesting as it may be to be able to have another tool to do what I could do with Entities. Just separating code somewhere else does not feel
like much of an upside, at least to me.
So, my question is: can one with DTO also access - in the instance of this course - the daily stats data source and add the corresponding output to the DTO?
Or, generally speaking, can one add any external source, like complex queries coming from the repositories ( group by, sum, multiple tables ) to the output.
Hey Bernard A.!
Hmm. Can you ask this again... I don't quite understand yet. Are you asking if you could... add OTHER data to an output DTO? If so... my answer is "sure, you can add whatever you want to the DTO... because you could do whatever custom stuff you want in the "data provider". But I think that I am not really answering your question yet ;).
Cheers!
Not quite answering my question. really! :)
And you threw a curve ball now when you mentioned "data provider".
At least in this course you did not bring up a DataProvider in connection with DTO/DataTransformer.
All is happening here is that - as it seems to me - you are refactoring code within the Entity out to DTO/DataTransformer.
When one wanted to add data from an external source, as in your case with DailyStat, or mine with GROUP BY query, one had to reach for a DataProvider.
If there is or could be a connection from the DataTransformer to the DataProvider I am at a bit of a loss.
The DataTransformer has only one actual working method which is "transform".
So, you are saying that one can on 'transform" access the DataProvider info. How?
Hey Bernard A.!
Hmm. Ok, let's back up :). Can you explain (on a high level, not really thinking about the code) what you'd like to accomplish?
So yes, when you use an "output DTO", then you have a data transformer, whose job is to "transform" from the source entity into the "output DTO" object. The
transform()method is passed the entity object... and you use it to create and populate the DTO object. If your goal is to add extra data to the DTO - data that is not directly on the entity, but is instead from some custom query that you create - then you are free to add that inside of the data transformer. For example, inCheeseListingOutputDataTransformer, I could inject theCheeseListingRepository, create a custom query inside oftransform(), and use that result to populate some properties onCheeseListingOutput.Does that help? I'm still not sure I'm directly answering your question, but hopefully we're closer at least :).
Cheers!
That will do, thanks!
There's one thing which isn't covered by this course, yet makes my brain explode and crash.
I'm trying to make my API use exclusively DTOs for both input and output. Furthermore, I want to reuse same classes for both input and output.
This works fine so long as I'm not trying to send embedded objects via JSON. However, I hit a very thick and sturdy wall as soon as I attempt to do that. I've been banging my head and trying to break that wall for a few weekdays already, to no avail. The problem is, It seems that even though I specify an input class for a resource which I'm sending embedded, a denormalizer for that DTO class is never called, and neither is the DTO to Entity transformer. Instead, Api Platform attempts to denormalize my input directly into the Entity class, creates an entity full of null values, and then causes an exception when trying to save that very very broken value into the database.
I'm talking about Api Platform 2.5 here. I sure hope that this is fixed in 2.6, but I need to investigate whether or not that is the case.
Does this sound familiar? Do you maybe have an idea about how I could solve this problem?
Edit: I've filed this as a bug in GitHub after chatting to Kévin on slack.
Hey Adeoweb!
It sounds like you already answered your question by talking with Kévin. I was also going to guess "bug" because the DTO's, in general, have quirks (as you saw in this video). So it definitely seems to me like you tripped over yet another quirk. When things get SUPER custom, this is one big reason I lean towards totally custom API classes, instead of entity classes with DTO's. But there are so many use-cases, and what's best varies.
Good luck!
Thanks! Actually, totally custom classes is also what Kévin suggested. But I just don't feel like willing to lose all the perks that come with Doctrine-based resources (yet), such as pagination.
FAIR point :). So you're stuck choosing the "best available option"... but nothing is perfect! Ah, programming...
Haha, so true! :D
Hi Ryan,
Is there a way to add the ApiResource configuration to a DTO by yaml file format? I'm struggling with that.
Hey Tuan Vu !
Hmm, I've never tried! From my reading, a DTO should not look any different than an "entity" resource - https://api-platform.com/docs/core/getting-started/#product
As long as you create that
config/api_platform/resources.yamlfile and point to it fromconfig/packages/api_platform.yaml, things should work.Are you getting an error... or API Platform is just not seeing your DTO at all?
Cheers!
"Houston: no signs of life"
Start the conversation!