Skip to content

Commit cd65469

Browse files
fix(operations): remove legacy doc about controllers (#2197)
Will fix #2134
1 parent acaf29c commit cd65469

File tree

1 file changed

+0
-164
lines changed

1 file changed

+0
-164
lines changed

core/operations.md

Lines changed: 0 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -479,167 +479,3 @@ resources:
479479
API Platform will find the operation matching this `itemUriTemplate` and use it to generate the IRI.
480480

481481
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

Comments
 (0)