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!
17.
Custom Resource Data Provider
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
}
}
10 Comments
Hey guys, I have one problem related to custom data provider.
What I need:
Need to group data from specific table. So the data collection not will return array of entities but just array of arrays (because doctrine not will be able to transform these data into entity).
I need to transform these arrays into specific dto (Output DTO that I use).
I thought that DataTransformer will help me but it's not. It just not triggered if data provider not return array of entities.
What is the best solution for this ?
PS. I'm not using custom controller with invoke method because I will lose some features of api platform. In my data provider I support filters and so on.
Hey Alex H.!
Hmm. This sounds a bit like a custom API resource entirely to me. Normally, I would also think to use an output DTO. But that assumes that your data provider would still return an array of entities... and then you would simply transform those in some way. This sounds more extreme (not in a bad way): you want to return a completely different set of data.
So, that's my first thought: a custom API resource class entirely. But I know that those can be annoying, as you need to re-add filtering, etc manually :/. Unfortunately, at the moment, I can't think of another decent way to do this.
Sorry I can't help more! Let me know if I've misunderstood any part of your question. When you said "need to group data", I assume that you are actually doing some sort of "GROUP BY" in your query, and so the results are very different than normal "rows in the table".
Cheers!
weaverryan thank you very much for answer. Didn't noticed that you answered.
You understood correctly related to "group by".
I will answer here the solution that I found and maybe you or other people will say if this solution is the best one.
As I said, the data that I get is totally different from the entity because I use some aggregated functions in the query, I make some calculation like average and so on.
My solution was to make custom collection after this I added also custom output DTO and custom data provider.
In my custom data provider I'm applying all extensions of api platform in order to not lose basic functionality.
After getting response from repository I'm transforming manually the data into my output DTO, so my data provider return array of DTO.
PS. I thought that if my provider will return array of arrays, I will be able to use standard data transformer of api platform but it's not triggered, so for this reason I made transformation inside the data provider.
PS. related to data transformer, I think that the problem is that method getCollection don't return array of entity.
Hey Alex H.!
Nice work! That's... pretty complex - but it's a complex solution - thank you for sharing it :).
Cheers!
Between, if you or someone else have better solution and not so complex, please share with me. I'm sure that many people searching for this.
Anybody already tried to inject the pagination extension? I can't find any example in which the data is retrieved by the collectionDataProvider->getCollection() instead of the queryBuilder. Any suggestions?
Yo @Arthur!
Are you building a data provider that ultimately pulls from Doctrine? Or is it a completely custom data provider that gets the data from somewhere else? Usually, if I just want to modify how the data is pulled for a Doctrine entity, I'll create a custom data provider, but then (once I'm done with my modifications) call the existing data provider system so that all the normal magic (like pagination, etc) is done - so this approach https://symfonycasts.com/sc...
I know the API Platform docs talk about injecting the "extensions" into your custom data provider - https://api-platform.com/do... - but I've never had to do that. What is your use-case? And can you clarify what you mean by:
> I can't find any example in which the data is retrieved by the collectionDataProvider->getCollection() instead of the queryBuilder.
Cheers!
I solved everything with doctrine extensions now. Don't know the best practise? Provider or extension? But for me it works great now.
Hey @Arthur!
Excellent! I would say that the best practice is to use an extension when you're able to because. This is a "smaller" hook: you're letting API Platform do its custom logic, and you simply modify the query right in the middle of it. The only time I would use a full custom provider is if I need to do something *beyond* modifying the query - e.g. I'm pulling data from somewhere *other* than the database... or perhaps I want to fetch the objects and then call some custom method on them to populate an extra field of data. But even in this last case, I would still call the core, Doctrine entity data provider from my custom data provider so that it does all the heavy lifting for me :).
Cheers!
He weaverryan!
Thanks for your fast reply. Although I'm using the dataprovider like in the 'Leveraging the Doctrine Data Provider'-course I loose al extra hydra data like pagination, total items etc. Also I'm not able to use filters in these entities.
In the api-platform injecting extensions example they do not use the collectionDataProvider getCollection method but build a query using the query builder. That's ok, but I prefer to use the platform logic.
Well all I want is collecting data with hydra information included and the possibility to use filters with these entities :) Do you have some magic for that?
Thanks!
"Houston: no signs of life"
Start the conversation!