@@ -479,167 +479,3 @@ resources:
479
479
API Platform will find the operation matching this ` itemUriTemplate ` and use it to generate the IRI.
480
480
481
481
If this option is not set, the first ` Get ` operation is used to generate the IRI.
482
-
483
- ## Expose a Model Without Any Routes
484
-
485
- Sometimes, you may want to expose a model, but want it to be used through subrequests only, and never through item or collection operations.
486
- Because the OpenAPI standard requires at least one route to be exposed to make your models consumable, let's see how you can manage this kind
487
- of issue.
488
-
489
- Let's say you have the following entities in your project:
490
-
491
- ``` php
492
- <?php
493
- // api/src/Entity/Place.php
494
- namespace App\Entity;
495
-
496
- use Doctrine\ORM\Mapping as ORM;
497
-
498
- #[ORM\Entity]
499
- class Place
500
- {
501
- #[ORM\Id, ORM\Column, ORM\GeneratedValue]
502
- private ?int $id = null;
503
-
504
- #[ORM\Column]
505
- private string $name = '';
506
-
507
- #[ORM\Column(type: 'float')]
508
- private float $latitude = 0;
509
-
510
- #[ORM\Column(type: 'float')]
511
- private float $longitude = 0;
512
-
513
- // ...
514
- }
515
- ```
516
-
517
- ``` php
518
- <?php
519
- // api/src/Entity/Weather.php
520
- namespace App\Entity;
521
-
522
- class Weather
523
- {
524
- private float $temperature;
525
-
526
- private float $pressure;
527
-
528
- // ...
529
- }
530
- ```
531
-
532
- We don't save the ` Weather ` entity in the database, since we want to return the weather in real time when it is queried.
533
- Because we want to get the weather for a known place, it is more reasonable to query it through a subresource of the ` Place ` entity, so let's do this:
534
-
535
- ``` php
536
- <?php
537
- // api/src/Entity/Place.php
538
- namespace App\Entity;
539
-
540
- use ApiPlatform\Metadata\Get;
541
- use ApiPlatform\Metadata\Put;
542
- use ApiPlatform\Metadata\Delete;
543
- use ApiPlatform\Metadata\GetCollection;
544
- use ApiPlatform\Metadata\Post;
545
- use ApiPlatform\Metadata\ApiResource;
546
- use App\Controller\GetWeather;
547
- use Doctrine\ORM\Mapping as ORM;
548
-
549
- #[ApiResource(
550
- operations: [
551
- new Get(),
552
- new Put(),
553
- new Delete(),
554
- new Get(name: 'weather', uriTemplate: '/places/{id}/weather', controller: GetWeather::class),
555
- new GetCollection(),
556
- new Post(),
557
- ]
558
- )]
559
- #[ORM\Entity]
560
- class Place
561
- {
562
- // ...
563
- ```
564
-
565
- The ` GetWeather ` controller fetches the weather for the given city and returns an instance of the ` Weather ` entity.
566
- This implies that API Platform has to know about this entity, so we will need to make it an API resource too:
567
-
568
- ``` php
569
- <?php
570
- // api/src/Entity/Weather.php
571
- namespace App\Entity;
572
-
573
- use ApiPlatform\Metadata\ApiResource;
574
-
575
- #[ApiResource]
576
- class Weather
577
- {
578
- // ...
579
- ```
580
-
581
- This will expose the ` Weather ` model, but also all the default CRUD routes: ` GET ` , ` PATCH ` , ` DELETE ` and ` POST ` , which is nonsense in our context.
582
- Since we are required to expose at least one route, let's expose just one:
583
-
584
- ``` php
585
- <?php
586
- // api/src/Entity/Weather.php
587
- namespace App\Entity;
588
-
589
- use ApiPlatform\Metadata\ApiResource;
590
- use ApiPlatform\Metadata\Get;
591
-
592
- #[ApiResource(operations: [
593
- new Get(controller: SomeRandomController::class)
594
- ])]
595
- class Weather
596
- {
597
- // ...
598
- }
599
- ```
600
-
601
- This way, we expose a route that will do… nothing. Note that the controller does not even need to exist.
602
-
603
- It's almost done, we have just one final issue: our fake item operation is visible in the API docs.
604
- To remove it, we will need to [ decorate the Swagger documentation] ( openapi.md#overriding-the-openapi-specification ) .
605
- Then, remove the route from the decorator:
606
-
607
- ``` php
608
- <?php
609
- // src/OpenApi/OpenApiFactory.php
610
- namespace App\OpenApi;
611
-
612
- use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
613
- use ApiPlatform\OpenApi\OpenApi;
614
- use ApiPlatform\OpenApi\Model;
615
-
616
- final class OpenApiFactory implements OpenApiFactoryInterface
617
- {
618
- private $decorated;
619
-
620
- public function __construct(OpenApiFactoryInterface $decorated)
621
- {
622
- $this->decorated = $decorated;
623
- }
624
-
625
- public function __invoke(array $context = []): OpenApi
626
- {
627
- $openApi = $this->decorated->__invoke($context);
628
-
629
- $paths = $openApi->getPaths()->getPaths();
630
-
631
- $filteredPaths = new Model\Paths();
632
- foreach ($paths as $path => $pathItem) {
633
- // If a prefix is configured on API Platform's routes, it must appear here.
634
- if ($path === '/weathers/{id}') {
635
- continue;
636
- }
637
- $filteredPaths->addPath($path, $pathItem);
638
- }
639
-
640
- return $openApi->withPaths($filteredPaths);
641
- }
642
- }
643
- ```
644
-
645
- That's it: your route is gone!
0 commit comments