# Subresources
A Subresource is another way of declaring a resource that usually involves a more complex URI.
In API Platform you can declare as many `ApiResource` as you want on a PHP class
creating Subresources.
Subresources work well by implementing your own state [providers](./state-providers.md)
or [processors](./state-processors.md). In API Platform we provide a working Doctrine layer for
subresources providing you add the correct configuration for URI Variables.
## URI Variables Configuration
URI Variables are configured via the `uriVariables` node on an `ApiResource`. It's an array indexed by the variables present in your URI, `/companies/{companyId}/employees/{id}` has two uri variables `companyId` and `id`. For each of these, we need to create a `Link` between the previous and the next node, in this example the link between a Company and an Employee.
If you're using the Doctrine implementation, queries are automatically built using the provided links.
### Answer to a Question
For this example we have two classes, a Question and an Answer. We want to find the Answer to
the Question about the Universe using the following URI: `/question/42/answer`.
Let's start by defining the resources:
```php
id;
    }
    // ...
}
// api/src/Entity/Question.php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
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)]
    public Answer $answer;
    public function getId(): ?int
    {
        return $this->id;
    }
    // ...
}
```
```yaml
# api/config/api_platform/resources.yaml
resources:
    App\Entity\Answer: ~
    App\Entity\Question: ~
```
```xml
    
    
```
Now to create a new way of retrieving an Answer we will declare another resource on the `Answer` class.
To make things work, API Platform needs information about how to retrieve the `Answer` belonging to
the `Question`, this is done by configuring the `uriVariables`:
```php
 new Link(
            fromClass: Question::class,
            fromProperty: 'answer'
        )
    ], 
    operations: [new Get()]
)]
class Answer
{
    // ...
}
```
```yaml
# api/config/api_platform/resources.yaml
resources:
    App\Entity\Answer:
        uriTemplate: /questions/{id}/answer
        uriVariables:
            id:
                fromClass: App\Entity\Question
                fromProperty: answer
        operations:
            ApiPlatform\Metadata\Get: ~
    App\Entity\Question: ~
```
```xml
    
    
    
    
        
            
        
        
            
        
    
    
```
In this example, we instructed API Platform that the `Answer` we retrieve comes **from** the **class** `Question`
**from** the **property** `answer` of that class.
URI Variables are defined using Links (`ApiPlatform\Metadata\Link`). A `Link` can be binded either from or to a class and a property.
If we had a `relatedQuestions` property on the `Answer` we could retrieve the collection of related questions via the following definition:
```php
#[ApiResource(
    uriTemplate: '/answers/{id}/related_questions.{_format}',
    uriVariables: [
        'id' => new Link(fromClass: Answer::class, fromProperty: 'relatedQuestions')
    ], 
    operations: [new GetCollection()]
)]
```
```yaml
# api/config/api_platform/resources.yaml
resources:
    App\Entity\Question:
        uriTemplate: /answers/{id}/related_questions.{_format}
        uriVariables:
            id:
                fromClass: App\Entity\Answer
                fromProperty: relatedQuestions
        operations:
            ApiPlatform\Metadata\GetCollection: ~
```
```xml
    
        
    
    
        
    
```
### Company Employee's
Note that in this example, we declared an association using Doctrine only between Employee and Company using a ManyToOne. There is no inverse association hence the use of `toProperty` in the URI Variables definition.
The following declares a few subresources:
    - `/companies/{companyId}/employees/{id}` - get an employee belonging to a company
    - `/companies/{companyId}/employees` - get the company employee's
```php
 new Link(fromClass: Company::class, toProperty: 'company'),
        'id' => new Link(fromClass: Employee::class),
    ],
    operations: [ new Get() ]
)]
#[ApiResource(
    uriTemplate: '/companies/{companyId}/employees',
    uriVariables: [
        'companyId' => new Link(fromClass: Company::class, toProperty: 'company'),
    ],
    operations: [ new GetCollection() ]
)]
class Employee
{
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
    public ?int $id;
    #[ORM\Column]
    public string $name;
    #[ORM\ManyToOne(targetEntity: Company::class)]
    public ?Company $company;
    public function getId()
    {
        return $this->id;
    }
}
```
Now let's add the Company class:
```php
 new Link(fromClass: Employee::class, fromProperty: 'company'),
    ],
    operations: [
        new Get()
    ]
)]
class Company {
    // ...
}
```
## Security
In order to use Symfony's built-in security system on subresources the security option of the `Link` attribute can be used.
To restrict the access to a subresource based on the parent object simply use the Symfony expression language as you would do normally, with the exception that the name defined in `toProperty` or `fromProperty` is used to access the object.
Alternatively you can also use the `securityObjectName` to set a custom name.
```php
 new Link(fromClass: Employee::class, toProperty: 'company', security: "is_granted(some_voter, company)"),
    ],
    operations: [
        new Get()
    ]
)]
class Company {
    // ...
}
```
This is currently an experimental feature disabled by default. To enable it please set `enable_link_security` to true:
```yaml
# api/config/packages/api_platform.yaml
api_platform:
    enable_link_security: true
```