Replies: 9 comments
-
|
I am struggling with the exact same problem for weeks now. I've summarized some of my research here, if you want to take a look: For inputs, we don't have a satisfying result right now. For Outputs, we've end up to use a mix of serializer groups, with custom source/target attributes if needed. |
Beta Was this translation helpful? Give feedback.
-
|
It's really interesting, could we add this example on https://github.com/mtarld/sfcon-apip/ ? We're trying to get a nice reference for this out there then we'll fix our docs. |
Beta Was this translation helpful? Give feedback.
-
|
@solariox // Book entity
class Book
{
#[ORM\ManyToOne(inversedBy: 'books')]
private ?Author $author = null;
}
// Author Entity
// Multiple Map attribute not works automatically :(
#[Map(target: OutputAuthorDTO::class)]
#[Map(target: AnotherOutputAuthorDTO::class)]
class Author {
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\OneToMany(targetEntity: Book::class, mappedBy: 'author')]
private Collection $books;
}
// DTO 1
class OutputAuthorDTO
{
public string $name;
}
// DTO 2
class AnotherOutputAuthorDTO
{
public string $books;
}
// Book resource
#[ApiResource(
stateOptions: new Options(entityClass: Book::class)
)]
#[GetCollection(
uriTemplate: '/books',
provider: BookResourceProvider::class,
)]
#[Map(source: Book::class)]
class BookResource
{
public OutputAuthorDTO $author;
#[Map(source: 'author')]
public AnotherOutputAuthorDTO $anotherAuthor;
}With this config, I gets error: If I swap these 2 #[Map] attributes, then I gets error: So, I guess the last #[Map] attribute is taken into account. |
Beta Was this translation helpful? Give feedback.
-
|
I don't understand could you explain what you want to achieve? |
Beta Was this translation helpful? Give feedback.
-
|
I created this discussion because I didn't know how to bind 2 DTO classes as associations using stateOptions and the symfony/object-mapper library. @solariox did a good research and presented several ways how to accomplish this. |
Beta Was this translation helpful? Give feedback.
-
|
I read @solariox gist, the thing I'm missing is the big picture. If you need Or are you using different operations on the same resource? Because if I Maybe the solution is to have different ApiResource classes for different use What's your use case specifically - do you need the same Book resource to |
Beta Was this translation helpful? Give feedback.
-
|
I pushed a minimal reproducer for the Api/Resource association issue with ObjectMapper. #[ApiProperty(readableLink: false, writableLink: false)] is ignored in my reproducer, and i fail to make a POST with en nested IRI. |
Beta Was this translation helpful? Give feedback.
-
|
Idea : Decorate ObjectMapperMetadataFactoryInterface to inject a specific mapping when the target is a Doctrine entity. The mapping would include a class transformer that retrieves the managed Doctrine entity using the correct primary keys and the provided state options. |
Beta Was this translation helpful? Give feedback.
-
|
After testing many things with the ObjectMapper component in my project and going through a lot of frustration, I ended up reimplementing the ObjectMapper component to support factories, injectable services for global transformations, predefined mappings based on a given source and target, and other features. The interface contract is not complicated (map source & target). That part is done. I started using it with ApiPlatform integration. For read operations, there is no issue; I did not have any with the original component either (except for nested class transforms, but that has been fixed since this morning). However, for write operations (POST/PATCH/PUT), the first problems I encounter are the following: In ObjectMapperProcessor, on a POST request, $request?->attributes->get('mapped_data') is empty, which is logical for a creation. As a result, the expected class is not even sent to the mapper, which then picks randomly among the possible mappings (and in my implementation, no mapping is allowed without an identified target, so this results in an error). So I added the StateOptionsTrait trait and modified the call to $this->decorated->process as follows: I also noticed that the return: does not take a potential output DTO into account. It will be a problem on somes of my endpoints. For “de-mapping” when you pass a DTO with properties that are ApiResources, I wrote a ClassTransform that directly fetches the Doctrine entity. I think I can improve it by leveraging the ApiProperty attributes to decide whether it should just take the entity (IRI provided) or also map what it contains (writableLink). I’m going to look into making this ClassTransform automatically applied when the target is a Doctrine entity, so I don’t have to hardcode it into every Map attribute. Probably a decorator around the mapping builder. Then I have an issue with my security layer. I need access to Doctrine entity properties to determine whether the user can perform certain actions or not. From what I understand at this stage, ObjectMapperProcessor runs after post_denormalize and post_validate. So I started looking into how to work around this. It would require either a security_post_mapper hook or a reordering so that the mapper runs after denormalization but before the security call in security_post_denormalize. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Supose I have two Entity classes:
And also I have two DTO classes:
#[ApiResource( operations: [ new Get(), new GetCollection(), ], stateOptions: new Options(entityClass: BookEntity::class) )] class BookApi { public int $id; public string $title; public AuthorApi $author; } #[ApiResource( operations: [ new Get(), new GetCollection(), ], stateOptions: new Options(entityClass: AuthorEntity::class) )] class AuthorApi { public int $id; public string $name; /** * array<BookApi> */ public array $books; }$authoras AuthorApi object (in BookApi) and$booksas collection (array) of BookApi objects (in AuthorApi)?$booksfield as collection of BookApi, but should be fetch BookEntity objects behind the scene?I don't want mix up entities with DTO classes, for example:
I tried to use "symfony/object-mapper" but no chance so far.
Thanks for Your help.
Beta Was this translation helpful? Give feedback.
All reactions