Skip to content
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

docs(dto): improve dto documentation and support laravel #2076

Open
wants to merge 1 commit into
base: 4.0
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions core/dto.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Using Data Transfer Objects (DTOs)

<p class="symfonycasts" style="text-align: center;"><a href="https://symfonycasts.com/api-platform-extending?cid=apip"><img src="../symfony/images/symfonycasts-player.png" alt="JWT screencast"><br>Watch the Custom Resources screencast</a></p>

As stated in [the general design considerations](design.md), in most cases [the DTO pattern](https://en.wikipedia.org/wiki/Data_transfer_object) should be implemented using an API Resource class representing the public data model exposed through the API and [a custom State Provider](state-providers.md). In such cases, the class marked with `#[ApiResource]` will act as a DTO.

However, it's sometimes useful to use a specific class to represent the input or output data structure related to an operation. These techniques are useful to document your API properly (using Hydra or OpenAPI) and will often be used on `POST` operations.
Expand All @@ -10,8 +12,7 @@ Using an input, the request body will be denormalized to the input instead of yo

```php
<?php
// api/src/Dto/UserResetPasswordDto.php

// api/src/Dto/UserResetPasswordDto.php with Symfony or app/Dto/UserResetPasswordDto.php with Laravel
namespace App\Dto;

use Symfony\Component\Validator\Constraints as Assert;
Expand All @@ -25,8 +26,7 @@ final class UserResetPasswordDto

```php
<?php
// api/src/Model/User.php

// api/src/Model/User.php with Symfony or app/Model/User.php with Laravel
namespace App\Model;

use ApiPlatform\Metadata\Post;
Expand All @@ -41,8 +41,7 @@ And the processor:

```php
<?php
// api/src/State/UserResetPasswordProcessor.php

// api/src/State/UserResetPasswordProcessor.php with Symfony or app/State/UserResetPasswordProcessor.php with Laravel
namespace App\State;

use App\Dto\UserResetPasswordDto;
Expand Down Expand Up @@ -73,14 +72,13 @@ final class UserResetPasswordProcessor implements ProcessorInterface

In some cases, using an input DTO is a way to avoid serialization groups.

## Use Messenger With an Input DTO
## Use Symfony Messenger With an Input DTO

Let's use a message that will be processed by [Symfony Messenger](https://symfony.com/components/Messenger). API Platform has an [integration with messenger](./messenger.md), to use a DTO as input you need to specify the `input` attribute:

```php
<?php
// api/src/Model/SendMessage.php

// api/src/Model/SendMessage.php with Symfony or app/Model/SendMessage.php with Laravel
namespace App\Model;

use ApiPlatform\Metadata\Post;
Expand All @@ -99,9 +97,8 @@ To return another representation of your data in a [State Provider](./state-prov

```php
<?php
// api/src/Entity/Book.php

namespace App\Entity;
// api/src/ApiResource/Book.php with Symfony or app/ApiResource/Book.php with Laravel
namespace App\ApiResource;

use ApiPlatform\Metadata\Get;
use App\Dto\AnotherRepresentation;
Expand All @@ -113,8 +110,7 @@ class Book {}

```php
<?php
// api/src/State/BookRepresentationProvider.php

// api/src/State/BookRepresentationProvider.php with Symfony or app/State/BookRepresentationProvider.php with Laravel
namespace App\State;

use App\Dto\AnotherRepresentation;
Expand All @@ -136,15 +132,15 @@ final class BookRepresentationProvider implements ProviderInterface

## Implementing a Write Operation With an Output Different From the Resource

For returning another representation of your data in a [State Processor](./state-processors.md), you should specify your processor class in the `processor` attribute and same for your `output`.
For returning another representation of your data in a [State Processor](./state-processors.md), you should specify your processor class in
the `processor` attribute and same for your `output`.

<code-selector>

```php
<?php
// api/src/Entity/Book.php

namespace App\Entity;
// api/src/ApiResource/Book.php with Symfony or app/ApiResource/Book.php with Laravel
namespace App\ApiResource;

use ApiPlatform\Metadata\Post;
use App\Dto\AnotherRepresentation;
Expand All @@ -156,8 +152,9 @@ class Book {}

```yaml
# api/config/api_platform/resources.yaml
# The YAML syntax is only supported for Symfony
resources:
App\Entity\Book:
App\ApiResource\Book:
operations:
ApiPlatform\Metadata\Post:
output: App\Dto\AnotherRepresentation
Expand All @@ -167,6 +164,7 @@ resources:
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!-- api/config/api_platform/resources.xml -->
<!-- The XML syntax is only supported for Symfony -->

<resources xmlns="https://api-platform.com/schema/metadata/resources-3.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
Expand All @@ -188,7 +186,7 @@ Here the `$data` attribute represents an instance of your resource.

```php
<?php
// api/src/State/BookRepresentationProcessor.php
// api/src/State/BookRepresentationProcessor.php with Symfony or app/State/BookRepresentationProcessor.php with Laravel

namespace App\State;

Expand Down