drupal_noob
drupal_noob

Reputation: 21

Skolem IRI for Entity which uses a DTO to change the output response

I'm using the API platform v3.1.14

I'm using a DTO to return a custom output for an entity. However it is generating a skolem iri instead of the Entity.

I've tried the suggestions in DTO Api Platform v3 and https://github.com/api-platform/core/issues/5451 but it is not working.

Entity:

<?php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\KeyRepository;
use App\Dto\KeyOutput;
use App\State\KeyOutputProvider;
use ApiPlatform\Metadata\Post;

#[ApiResource(
    shortName: 'Key_new',
        operations: [
                new Post(),
        ],
)]
#[Get(
    uriTemplate: '/keys_new/{id}',
    shortName: 'Key_new',
    output: KeyOutput::class,
    provider: KeyOutputProvider::class,
    openapi: true,
  )]
#[ORM\Entity(repositoryClass: KeyRepository::class)]
class KeyNew {

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    public ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $title = null;

    public function getId(): int
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): self
    {
        $this->title = $title;

        return $this;
    }
}

DTO:

<?php

namespace App\Dto;
use App\State\KeyOutputProvider;
use ApiPlatform\Metadata\Get;


class KeyOutput
{
    public int $id;

    public string $title;
}


State Provider:

<?php

namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Dto\KeyOutput;
use App\Repository\KeyRepository;

final class KeyOutputProvider implements ProviderInterface
{
  public function __construct(private ProviderInterface $itemProvider, private KeyRepository $keyRepository)
  {
  }

    /**
     * {@inheritDoc}
     */
    public function provide(Operation $operation, array $uriVariables = [], array $context = []) : object | array
    {
      $key =  $this->keyRepository->find($uriVariables['id']);

      $output = new KeyOutput();
      $output->id = $key->getId();
      $output->title = $key->getTitle();
      return $output;
    }

  }

Tried: DTO Api Platform v3 https://github.com/api-platform/core/issues/5451

Skolem Uri is still generated for the @id.

I event tried to put the GET operation on the DTO, but it is not recognized.

Upvotes: 1

Views: 386

Answers (2)

Roman Petrovich
Roman Petrovich

Reputation: 21

Similar way helped me with same problem.

Thanks to Calliso, I added attribute for DTO class and it worked

#[Get(uriTemplate: '/products/{id}')]
class ProductDTO

Upvotes: 1

Calliso
Calliso

Reputation: 41

As stated in: https://github.com/api-platform/core/issues/5451#issuecomment-1464902089

You can mark your DTO with attribute with the same shortName as in Entity. So your DTO:

#[Get(shortName: 'Key_new')]
class KeyOutput{...

and entity:

#[ApiResource(
    shortName: 'Key_new',
        operations: [
                new Post(),
        ], )]
#[Get(
    uriTemplate: '/keys_new/{id}',
    shortName: 'Key_new',
    output: KeyOutput::class,
    provider: KeyOutputProvider::class,
    openapi: true,   )]
#[ORM\Entity(repositoryClass: KeyRepository::class)] 
class KeyNew {

But I think the best option is to mark your DTO as ApiResource, and leave Entity without ApiResource attribute. Unfortunately I'm not aware of any problems that you can occure marking DTO and Entity as ApiResource.

Upvotes: 2

Related Questions