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:
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)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.