PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Wednesday, May 11, 2022

[FIXED] Why do I get "No item route associated with the type" when using Api-Platform?

 May 11, 2022     api-platform.com, php, symfony     No comments   

Issue

My project is built in Symfony 5 and API-Platform to consume it from a JS client. In this scenario, I have a Question entity related to an Answer entity (One-to-many respectively).

Whenever I try to call /api/questions or /api/answers I get this error: "No item route associated with the type "App\Entity\Answer":

In order to API resources this is what I have configured with maker bundle:

- App\Entity\Question:

/**
 * @ORM\Entity(repositoryClass=QuestionRepository::class)
 * @ApiResource
 * @ApiFilter(SearchFilter::class, properties={"status": "exact"})
 */
class Question
{
    // ...
    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="questions")
     * @ORM\JoinColumn(nullable=false)
     */
    private $owner;

    // ... 

    /**
     * @ORM\OneToMany(targetEntity=Answer::class, mappedBy="question", orphanRemoval=true)
     */
    private $answers;

    // ...

    /**
     * @return Collection|Answer[]
     */
    public function getAnswers(): Collection
    {
        return $this->answers;
    }

    public function addAnswer(Answer $answer): self
    {
        if (!$this->answers->contains($answer)) {
            $this->answers[] = $answer;
            $answer->setQuestion($this);
        }

        return $this;
    }

    public function removeAnswer(Answer $answer): self
    {
        if ($this->answers->contains($answer)) {
            $this->answers->removeElement($answer);
            // set the owning side to null (unless already changed)
            if ($answer->getQuestion() === $this) {
                $answer->setQuestion(null);
            }
        }

        return $this;
    }

    // ...
}

- App\Entity\Answer:

/**
 * @ORM\Entity(repositoryClass=AnswerRepository::class)
 * @ApiResource
 */
class Answer
{
    // ...
    
    /**
     * @ORM\ManyToOne(targetEntity=Question::class, inversedBy="answers")
     * @ORM\JoinColumn(nullable=false)
     * @Assert\NotBlank
     */
    private $question;

    // ...

    public function getQuestion(): ?Question
    {
        return $this->question;
    }

    public function setQuestion(?Question $question): self
    {
        $this->question = $question;

        return $this;
    }
   
    // ...
}

Not sure if this is relevant to this issue: I configured config/api_platform/resources.yaml on api_platform.yaml:

App\Entity\Answer:
  attributes:
    security: 'is_granted("ROLE_USER")'
    security_message: 'Only the authenticated user can see answers'
  collectionOperations:
    get:
      security: 'is_granted("ROLE_USER")'
      security_message: 'Only the authenticated user can get answers'
    post:
      security: 'is_granted("ROLE_USER")'
      security_message: 'Only the authenticated user can save answers'
  itemOperations:
      put:
        security: 'is_granted("ROLE_ADMIN") or object.owner == user'
        security_message: 'Only the authenticated user or administrators can update answers'
      delete:
        security: 'is_granted("ROLE_ADMIN")'
        security_message: 'Only administrators can delete answers'

App\Entity\Question:
  attributes:
    security: 'is_granted("ROLE_USER")'
    security_message: 'Only the authenticated user can see questions'
  collectionOperations:
    get:
      security: 'is_granted("ROLE_ADMIN")'
      security_message: 'Only the authenticated user or administrators can get questions'
    post:
      security: 'is_granted("ROLE_USER")'
      security_message: 'Only the authenticated user can save questions'
  itemOperations:
      get:
        security: 'is_granted("ROLE_ADMIN") or object.owner == user'
        security_message: 'Only the authenticated user or administrators can get questions'
      put:
        security: 'is_granted("ROLE_ADMIN") or object.owner == user'
        security_message: 'Only the authenticated user or administrators can update questions'
      delete:
        security: 'is_granted("ROLE_ADMIN")'
        security_message: 'Only administrators can delete questions'

The Swagger UI displays information about Question and Answer entity resources:

And this is what debug:route displays regarding Answer:

  api_answers_get_collection                      GET        ANY      ANY    /api/answers.{_format}
  api_answers_post_collection                     POST       ANY      ANY    /api/answers.{_format}
  api_answers_put_item                            PUT        ANY      ANY    /api/answers/{id}.{_format}
  api_answers_delete_item                         DELETE     ANY      ANY    /api/answers/{id}.{_format}

What is wrong here?


Solution

TLDR:

For all resources, you need to have the basic **item ** GET /resource/{id} route.



The error message is very explicit:

No item route associated with the type "App\Entity\Answer"

If you check your resource definition for Answer you will see:

itemOperations:
      put:
        security: 'is_granted("ROLE_ADMIN") or object.owner == user'
        security_message: 'Only the authenticated user or administrators can update answers'
      delete:
        security: 'is_granted("ROLE_ADMIN")'
        security_message: 'Only administrators can delete answers'

So you basically only have delete and update routes, but do not have a basic item retrieve route (GET /api/answers/123). By defining the routes explicitly, whatever route you do not define you disable.

That is confirmed with the output from the API docs: enter image description here

Without that, it is impossible to get a valid IRI for the resource. Without a valid GET route for a resource the system cannot generate a URL for each resource item, and since those URLs/IRIs are used as identifiers by the system, these should always be defined.

You just need to add the configuration for the item route back:

itemOperations:
      put:
        security: 'is_granted("ROLE_ADMIN") or object.owner == user'
        security_message: 'Only the authenticated user or administrators can update answers'
      delete:
        security: 'is_granted("ROLE_ADMIN")'
        security_message: 'Only administrators can delete answers'
      get:
        security: 'is_granted("ROLE_USER")'
        security_message: 'Only the authenticated user can get answers'


Answered By - yivi
Answer Checked By - Marilyn (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing