# Subresources A subresource is a collection or an item that belongs to another resource. API Platform makes it easy to create such operations.

Subresources screencast
Watch the Subresources screencast

The starting point of a subresource must be a relation on an existing resource. For example, let's create two entities (Question, Answer) and set up a subresource so that `/question/42/answer` gives us the answer to the question 42: ```php id; } // ... } // api/src/Entity/Question.php namespace App\Entity; use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\Core\Annotation\ApiSubresource; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] #[ApiResource] class Question { #[ORM\Id, ORM\Column, ORM\GeneratedValue] private ?int $id = null; #[ORM\Column(type: 'text')] public string $content; #[ORM\OneToOne] #[ORM\JoinColumn(referencedColumnName: 'id', unique: true)] #[ApiSubresource] public Answer $answer; public function getId(): ?int { return $this->id; } // ... } ``` ```yaml # api/config/api_platform/resources.yaml App\Entity\Answer: ~ App\Entity\Question: properties: answer: subresource: resourceClass: 'App\Entity\Answer' collection: false ``` Note that all we had to do is to set up `#[ApiSubresource]` on the `Question::answer` relation. Because the `answer` is a to-one relation, we know that this subresource is an item. Therefore the response will look like this: ```json { "@context": "/contexts/Answer", "@id": "/answers/42", "@type": "Answer", "id": 42, "content": "Life, the Universe, and Everything", "question": "/questions/42" } ``` If you put the subresource on a relation that is to-many, you will retrieve a collection. Last but not least, subresources can be nested, such that `/questions/42/answer/comments` will get the collection of comments for the answer to question 42. Note: only for `GET` operations are supported at the moment ## Using Serialization Groups You may want custom groups on subresources, you can set `normalization_context` or `denormalization_context` on that operation. To do so, add a `subresourceOperations` node. For example: ```php [ 'method' => 'GET', 'normalization_context' => [ 'groups' => ['foobar'], ], ], ], )] class Answer { // ... } ``` ```yaml # api/config/api_platform/resources.yaml App\Entity\Answer: subresourceOperations: api_questions_answer_get_subresource: method: 'GET' normalization_context: {groups: ['foobar']} ``` ```xml GET foobar ``` In the previous examples, the `method` attribute is mandatory, because the operation name doesn't match a supported HTTP method. Note that the operation name, here `api_questions_answer_get_subresource`, is the important keyword. It'll be automatically set to `$resources_$subresource(s)_get_subresource`. To find the correct operation name you may use `bin/console debug:router`. ## Using Custom Paths You can control the path of subresources with the `path` option of the `subresourceOperations` parameter. ```php [ 'method' => 'GET', 'path' => '/questions/{id}/all-answers', ], ], )] class Question { } ``` ### Access Control of Subresources The `subresourceOperations` attribute also allows you to add an access control on each path with the attribute `security`. ```php [ 'security' => "is_granted('ROLE_AUTHENTICATED')", ], ], )] class Answer { } ``` ### Limiting Depth You can control depth of subresources with the parameter `maxDepth`. For example, if the `Answer` entity also has a subresource such as `comments` and you don't want the route `api/questions/{id}/answers/{id}/comments` to be generated. You can do this by adding the parameter maxDepth in the ApiSubresource annotation or YAML/XML file configuration. ```php