Skip to content

Commit 9d659e1

Browse files
committed
Subresource definition ADR proposal
1 parent 04142a6 commit 9d659e1

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# [short title of solved problem and solution]
2+
3+
* Status: proposed
4+
* Deciders: @dunglas, @vincentchalamon, @soyuka, @GregoireHebert, @Deuchnord
5+
6+
## Context and Problem Statement
7+
8+
Subresources introduced in 2017 (#904) introduced the `ApiSubresource` annotation. This definition came along with its own set of issues (#2706) and needs a refreshment. On top of that, write support on subresources is a wanted feature and it is hard to implement currently (#2598) (See [0001-subresource-write-support](./0001-subresource-write-support.md)). How can we revamp subresources to improve the developer experience and reduce the complexity?
9+
10+
## Considered Options
11+
12+
* Fix the actual `ApiSubresource` annotation
13+
* Use multiple `ApiResource` to declare subresources and deprecate `ApiSubresource`
14+
* Deprecate subresources
15+
16+
## Decision Outcome
17+
18+
We choose to use multiple `ApiResource` annotations to declare subresources on a given Model class:
19+
20+
* Subresource declaration is an important feature and removing it would harm the software.
21+
* The `ApiSubresource` annotation is declared on a Model's properties, which was identified as the root of several issues. For example, finding what class it is defined on (#3458). Having multiple `ApiResource` would improve a lot the declaration of our internal metadata and would cause less confusion for developers.
22+
* The `path` of these multiple `ApiResource` needs to be implicitly described.
23+
24+
### Examples
25+
26+
A Company resource with a Company Users subresource on (`/companies/1/users`);
27+
28+
```php
29+
/**
30+
* @ApiResource()
31+
* @ApiResource(path="/companies/{companyId}/users")
32+
*/
33+
class Company {
34+
public int $id;
35+
public array $users = [];
36+
}
37+
```
38+
39+
With explicit identifiers:
40+
41+
```php
42+
/**
43+
* @ApiResource()
44+
* @ApiResource(path="/companies/{companyId}/users", identifiers={"companyId": {Company::class, "id"}})
45+
*/
46+
class Company {
47+
public int $id;
48+
public array $users = [];
49+
}
50+
```
51+
52+
Two-level subresource to get the users belonging to the company 1 located in France `/countries/fr/companies/1/users`:
53+
54+
```php
55+
/**
56+
* @ApiResource()
57+
* @ApiResource(path="/countries/{countryId}/companies/{companyId}/users")
58+
*/
59+
class Country {
60+
public int $id;
61+
public array $companies = [];
62+
}
63+
```
64+
65+
With explicit identifiers:
66+
67+
```php
68+
/**
69+
* @ApiResource()
70+
* @ApiResource(path="/countries/{countryId}/companies/{companyId}/users", identifiers={"companyId": {Company::class, "id"}, "countryId": {Country::class, "shortName"}})
71+
*/
72+
class Country {
73+
public string $shortName;
74+
public array $companies = [];
75+
}
76+
```
77+
78+
Get the company employees or administrators `/companies/1/administrators`:
79+
80+
```php
81+
/**
82+
* @ApiResource()
83+
* @ApiResource(path="/companies/{companyId}/administrators")
84+
* @ApiResource(path="/companies/{companyId}/employees")
85+
*/
86+
class Company {
87+
public int $id;
88+
public Users $employees;
89+
public Users $administrators;
90+
}
91+
```
92+
93+
With explicit identifiers:
94+
95+
```php
96+
/**
97+
* @ApiResource()
98+
* @ApiResource(path="/companies/{companyId}/administrators", identifiers={"companyId": {Company::class, "id"}, "*": {Company::class, "administrators"}})
99+
* @ApiResource(path="/companies/{companyId}/employees", identifiers={"companyId": {Company::class, "id"}, "*": {Company::class, "employees"}})
100+
*/
101+
class Company {
102+
public int $id;
103+
public Users $employees;
104+
public Users $administrators;
105+
}
106+
```
107+
108+
## TODO:
109+
110+
* Without explicit identifiers, how do we map `companyId` to Company->id ?
111+
* Do we parse the path to find `administrators` and map it to the property ?
112+
* The Tuple `identifiers={pathParameter: {Class, property}}` should be redefined / validated (and what about `*` for collection?)

0 commit comments

Comments
 (0)