-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with the resource transformer design pattern and cross relations #67
Comments
Hi, sorry to bother you again... Thanks anyway for this great lib and your hard work!!! |
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)! |
Hey, |
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:
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. |
Sorry didn't have the time to think it through.. but i will reply in detail soon... thanks for your ideas. |
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()
)
); |
@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 |
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 private $imageResourceTransformer;
public function setImageResourceTransformer(ImageResourceTransformer $imageResourceTransformer): void
{
$this->imageResourceTransformer = $imageResourceTransformer;
} In private $offerResourceTransformer;
public function setOfferResourceTransformer(OfferResourceTransformer $offerResourceTransformer): void
{
$this->offerResourceTransformer = $offerResourceTransformer;
} In App\JsonApi\Transformer\OfferResourceTransformer:
calls:
- method: setImageResourceTransformer
App\JsonApi\Transformer\ImageResourceTransformer:
calls:
- method: setOfferResourceTransformer And now it works like a charm! |
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). |
When using cross relations between 2 resources the current design pattern used by the yin resource transformers has the issue of circular dependencies. I think it is necessary to cross relate objects. For example:
I solved this in my case outside of the lib with injecting just a container into the transformers which can require the transformers on demand. But in my opinion this should be solved by the lib itself.
The neomerx lib solves this by mapping the transformers "hard" with the models.. but i liked your modular "loose" approach here.. so maybe a factory patter where one needs to register all transformers and a factory where you can get them whenever you need them could solve the problem.
The text was updated successfully, but these errors were encountered: