Core: DTO DataTransformer not called in v2.5.4

Created on 27 Feb 2020  路  4Comments  路  Source: api-platform/core

API Platform version(s) affected: 2.5.4. Also tried with 2.4.7 same result

Following the instructions for setting up DTOs with DataTransformers using yaml configuration. https://api-platform.com/docs/core/dto

resources:

    App\Domain\Model\Booking\Booking:
        attributes:
            output: App\Application\Api\BookingOutput

The BookingOutput DTO class is picked up - it's displayed in the Schemas in the Swagger UI etc.

However, it appears the DataTransformer is never even called. All it does it return the Doctrine entity of the main resource App\Domain\Model\Booking\Booking instead of the DTO.

The supportsTransformation() method is never called.

The transformer is registered in the container, although the note at the bottom makes me wonder if it's removed because it hasn't been used:

bin/console debug:container BookingOutputDataTransformer

Information for Service "App\Infrastructure\Api\DataTransformer\BookingOutputDataTransformer"
=================================================================================================================

 ---------------- ----------------------------------------------------------------------------------------- 
  Option           Value                                                                                    
 ---------------- ----------------------------------------------------------------------------------------- 
  Service ID       App\Infrastructure\Api\DataTransformer\BookingOutputDataTransformer  
  Class            App\Infrastructure\Api\DataTransformer\BookingOutputDataTransformer  
  Tags             api_platform.data_transformer                                                            
  Public           no                                                                                       
  Synthetic        no                                                                                       
  Lazy             no                                                                                       
  Shared           yes                                                                                      
  Abstract         no                                                                                       
  Autowired        yes                                                                                      
  Autoconfigured   yes                                                                                      
 ---------------- ----------------------------------------------------------------------------------------- 


 ! [NOTE] The "App\Infrastructure\Api\DataTransformer\BookingOutputDataTransformer" service or   
 !        alias has been removed or inlined when the container was compiled.                                         

The DataTransformer class:

final class BookingOutputDataTransformer implements DataTransformerInterface
{
    /**
     * @param Booking $data
     */
    public function transform($data, string $to, array $context = [])
    {
        $output = new BookingOutput();
        $output->id = $data->id()->asString();
        $output->start = $data->rentalPeriod()->start()->format(Carbon::ATOM);
        $output->end = $data->rentalPeriod()->end()->format(Carbon::ATOM);

        return $output;
    }

    public function supportsTransformation($data, string $to, array $context = []): bool
    {
        return BookingOutput::class === $to && $data instanceof Booking;
    }
}

Any ideas why the DataTransformers are not being picked up?

Thanks

question

All 4 comments

The service seems to have been registered correctly. The note is not a concern.

You might want to place some dump calls in this method to see what's going on:

https://github.com/api-platform/core/blob/5fa9b567dd2b86cf40ff6f8784776535409bb321/src/Serializer/AbstractItemNormalizer.php#L650

Thanks for your reply. The transformOutput() method is not being called at all.

Neither is normalize() in the same class.

I've sent you a PM on Symfony Slack. Let's figure this out.

With help from @teohhanhui I've got to the bottom of the issue.

It is caused by having the Symfony PropertyNormalizer enabled as well. As soon as I disable this, the DataTransformers start working as expected and the output is the BookingOutput class instead of the Booking entity directly.

Apparently there is currently no way to use ApiPlatform with the PropertyNormalizer. My use case was that I didn't want to have "get" prefixes on my entity getters, as per DDD recommendations, but it seems this is not possible.

Apparently it'll be supported in Symfony 5.1, at least in the PropertyInfo component.

It's a bit early to say, but my use-case is that the API is only providing read-only data, so instead of messing with my domain model, I might publish all the data as a read model to Elasticsearch and then use ApiPlatform backed by Elasticsearch instead of Doctrine.

Was this page helpful?
0 / 5 - 0 ratings