@@ -213,3 +213,108 @@ final class BookRepresentationProcessor implements ProcessorInterface
213
213
}
214
214
}
215
215
```
216
+
217
+ ## Implementing one custom state provider with DTOs to support Get and GetCollection methods
218
+
219
+ We have a state provider named ` BookProvider ` which retrieves our data to serve them in our API using DTOs.
220
+ If we want to combine both Get and GetCollection methods into a single state provider as follows:
221
+
222
+ ``` php
223
+ <?php
224
+ // api/src/Resource/Book.php with Symfony or app/Resource/Book.php with Laravel
225
+
226
+ declare(strict_types=1);
227
+
228
+ namespace App\Resource;
229
+
230
+ use ApiPlatform\Metadata\ApiResource;
231
+ use App\State\BookProvider;
232
+ use ApiPlatform\Metadata\Get;
233
+ use ApiPlatform\Metadata\GetCollection;
234
+ use Doctrine\ORM\Mapping as ORM;
235
+ use Symfony\Component\Validator\Constraints as Assert;
236
+
237
+ #[Get(provider: BookProvider::class)]
238
+ #[GetCollection (provider: BookProvider::class)]
239
+ final class Book
240
+ {
241
+ #[ORM\Id]
242
+ #[ORM\GeneratedValue]
243
+ #[ORM\Column(type: 'integer')]
244
+ private ?int $id = null;
245
+
246
+ #[ORM\Column(type: 'string', length: 255)]
247
+ #[Assert\NotBlank]
248
+ private string $title;
249
+
250
+ // Other fields, accessors and mutators...
251
+ }
252
+ ```
253
+
254
+ To do that, we can create a state provider for both cases using this:
255
+
256
+ ``` php
257
+ <?php
258
+ // api/src/State/BookProvider.php with Symfony or app/State/BookProvider.php with Laravel
259
+
260
+ declare(strict_types=1);
261
+
262
+ namespace App\Resource;
263
+
264
+ use ApiPlatform\Metadata\ApiResource;
265
+ use ApiPlatform\State\ProviderInterface;
266
+ use ApiPlatform\Doctrine\Orm\State\CollectionProvider;
267
+
268
+ final class BookProvider implements ProviderInterface
269
+ {
270
+ public function __construct(
271
+ #[Autowire(service: CollectionProvider::class)]
272
+ private readonly ProviderInterface $collectionProvider,
273
+ ) {}
274
+
275
+ public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?PostalAddress
276
+ {
277
+ $resources = $this->collectionProvider->provide($operation, $uriVariables, $context);
278
+
279
+ $dtos = [];
280
+ foreach ($resources as $resource){
281
+ $dtos[] = new Book(
282
+ $resource->id,
283
+ $resource->title,
284
+ // ...
285
+ )
286
+ }
287
+
288
+ return $dtos;
289
+ }
290
+ }
291
+ ```
292
+
293
+ > [ !TIP]
294
+ > For more information and other advanced options, refer to the [ screencast here] ( #using-data-transfer-objects-dtos ) .
295
+
296
+ ## DTO without response
297
+
298
+ Sometimes we need DTOs to process something, but we don't need to send an object in response.
299
+ Assuming that, we can disable the output for our API Resource using the following code:
300
+
301
+ ``` php
302
+ <?php
303
+ // api/src/Resource/Book.php with Symfony or app/Resource/Book.php with Laravel
304
+
305
+ declare(strict_types=1);
306
+
307
+ namespace App\Resource;
308
+
309
+ use ApiPlatform\Metadata\ApiResource;
310
+ use App\Dto\BookInput;
311
+
312
+ #[ApiResource(
313
+ input: BookInput::class,
314
+ output: false, // Disables the response
315
+ )]
316
+ final class Book
317
+ {
318
+ // ...
319
+ }
320
+ ```
0 commit comments