Comments (9)
I know it's been a while, but I came across the same problem yesterday. I have an Offer entity that has many Images and each Image entity is related back to an Offer. I wanted to be able to include both Images with Offer and Offer with Image. After trying and failing for a while, I got it to work using Symfony's setter injection. The main trick is not to inject anything in the constructor because this is what makes the reference circle.
In OfferResourceTransformer
add the setter for ImageResourceTransformer
:
private $imageResourceTransformer;
public function setImageResourceTransformer(ImageResourceTransformer $imageResourceTransformer): void
{
$this->imageResourceTransformer = $imageResourceTransformer;
}
In ImageResourceTransformer
add the setter for OfferResourceTransformer
:
private $offerResourceTransformer;
public function setOfferResourceTransformer(OfferResourceTransformer $offerResourceTransformer): void
{
$this->offerResourceTransformer = $offerResourceTransformer;
}
In services.yaml
add:
App\JsonApi\Transformer\OfferResourceTransformer:
calls:
- method: setImageResourceTransformer
App\JsonApi\Transformer\ImageResourceTransformer:
calls:
- method: setOfferResourceTransformer
And now it works like a charm!
from yin.
Hi, sorry to bother you again...
it would be very nice if you could check this, because i think it is a bigger issue which everyone will face sooner or later. It would be best if it would be solved inside the lib, everything else feels like a dirty workaround.
Thanks anyway for this great lib and your hard work!!!
from yin.
Hey,
Sorry for leaving your issue unanswered so long, and thanks for bringing this up again. In the current months I am overwhelmed with other tasks and really busy at work. :/ So I didn't have possibility to think about the solution and respond you.
I'll answer you in detail in some days (and definitely not in many days)!
from yin.
Hey,
thanks for your reply. You just answer whenever you have time..
I just wanted to bring it up again so that it is not forgotten.
from yin.
I have thought about the problem since our last messages, and I believe, it should be solved outside of the library indeed. Here are the solutions which might work for you in my opinion:
-
The quick and dirty solution might be using property or setter injection if you have a DI Container. These methods effectively mitigate the problem of circular dependencies. Usually, I don't recommend these dependency injection types because they make a class not easy to unit test, but in this case, it's not a serious issue as JSON:API transformation is not usually unit tested.
-
A child class of an
AbstractTransformer
can have any dependency so you can implement your ownBookTransfomerFactory
which can create anAuthorTransformer
orBookTransformer
class. I admit that a Factory like that might not be easy to implement.
What do you think about these ideas? To be honest, I don't like the idea to register transformers because that would require an own Service Locator to be implemented and a plain old DI Container is just perfect for this purpose.
Sorry for the late response again.
from yin.
Sorry didn't have the time to think it through.. but i will reply in detail soon... thanks for your ideas.
from yin.
I don't think creating the graph of how transformers are related is the best alternative. I think you should specify the Transformer class when you create relationships. So it would looks like:
public function getRelationships($book): array
{
return [
"authors" => function (array $book) {
return ToManyRelationship::create()
->setLinks(
Links::createWithoutBaseUri()->setSelf(new Link("/books/relationships/authors"))
)
->setData($book["authors"], \AuthorTransformer)
;
},
"publisher" => function ($book) {
return ToOneRelationship::create()
->setLinks(
Links::createWithoutBaseUri()->setSelf(new Link("/books/relationships/publisher"))
)
->setData($book["publisher"], \PublisherTransformer)
;
}
];
}
You could instantiate them as needed and remove the need for this:
// Instantiating a book document
$document = new BookDocument(
new BookResourceTransformer(
new AuthorResourceTransformer(),
new PublisherResourceTransformer()
)
);
from yin.
@guilhermeaiolfi Yes i came up with that idea as well and actually solved it like that in another project. Sometimes the easy solutions are the hardest to find.. :D
And i totally agree, that this is the best approach here. The only thing considering would be, that we will end up with a lot of transformer instances. Transformers are stateless so they could be singletons without any issues.
Maybe @kocsismate should just change the examples to that easy approach because i'm sure a lot of people are running into the same issues here.
from yin.
Hi @jakagacic,
Thanks for sharing your example!
To give an answer to the prior discussion: as @guilhermeaiolfi suggested, transformers are not at all needed to be instantiated ahead of time, a DI container can easily do the job on-the-fly.
I don't plan to add better support for service location of transformers in Yin as I believe it can be still conveniently done in user-land code. However, I agree with @gfemorris , it could be noted in the examples and also in the read me that you have a choice when to instantiate the transformers (ahead-of-time via Dependency Injection or just-in-time via Service Location).
from yin.
Related Issues (20)
- Error in createResourceIdInvalidException HOT 3
- Parsed body always contains an empty array when using Symfony requests HOT 4
- Missing data in response if using omitDataWhenNotIncluded HOT 7
- Passing the DomainObject to the validateRequest() method of the hydrator class HOT 10
- [PHP8] Method ReflectionParameter::getClass() is deprecated HOT 3
- Data Transformer array_merge problem HOT 2
- The package doesn't support psr/http-message v2 HOT 1
- Using same temp stream in multiple requests HOT 1
- Possible bug in OffsetBasedPagination HOT 6
- Exception code 0 HOT 2
- Hydrating same type (child, parent) related entity HOT 2
- Feature request: InfoDocument support HOT 1
- How to hydrate a POST request with multiple resources HOT 4
- Content-Type and Accept headers not really under domain validation HOT 7
- Using validateJsonBody() before getResource() makes request body empty HOT 3
- Problem with recursive relations HOT 1
- AbstractLinks::transform() generates invalid "prev" / "next" links HOT 3
- Incorrect encoding of (pagination) query parameters HOT 6
- Throw Exception if 'data' and 'errors' coexist in the request body HOT 3
- Add support for PSR-17 Http factory HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from yin.