Skip to content

Commit

Permalink
docs: improve uri variables ADR
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Sep 29, 2021
1 parent e649fa1 commit a998b5f
Showing 1 changed file with 130 additions and 6 deletions.
136 changes: 130 additions & 6 deletions docs/adr/0003-uri-variables.md
Expand Up @@ -14,7 +14,8 @@ URI variables are the URI template (e.g. `/books/{id}`) variables (e.g. `id`). W
<?php
use Company;

#[Get("/companies/{companyId}/users/{id}", [identifiers=["companyId" => [Company::class, "id"], "id" => [User::class, "id"]]])]
#[ApiResource("/companies/{companyId}/users/{id}", [identifiers=["companyId" => [Company::class, "id"], "id" => [User::class, "id"]]])]
#[Get]
class User {
#[ApiProperty(identifier=true)]
public $id;
Expand All @@ -34,12 +35,12 @@ To make this work, API Platform needs to know what property of the class User ha
We will use a map to define URI variables, for now these options are available:

```
uriTemplate: [
uriVariables: [
'companyId' => [
'class' => Company::class,
'identifiers' => ['id'],
'composite_identifier' => true,
'property' => 'user'
'property' => 'company'
],
'id' => [
'class' => User::class,
Expand All @@ -48,7 +49,7 @@ uriTemplate: [
]
```

Where `uriTemplate` keys are the URI template's variable names. Its value is a map where:
Where `uriVariables` keys are the URI template's variable names. Its value is a map where:

- `class` is the PHP FQDN to the class this value belongs to
- `identifiers` are the properties of the class to which we map the URI variable
Expand All @@ -57,14 +58,137 @@ Where `uriTemplate` keys are the URI template's variable names. Its value is a m

As of PHP 8.1, PHP will support [nested attributes](https://wiki.php.net/rfc/new_in_initializers). We'll introduce a proper class as an alternative to the associative array when PHP 8.1 will be released.

Thanks to these we can build our query which in this case is (pseudo-SQL):
Thanks to these we can build our query which in this case is (pseudo-SQL) to fetch the user belonging to a company (`/companies/{companyId}/users/{id}`):

```sql
SELECT * FROM User::class u
JOIN u.company c
WHERE u.id = :id AND c.id = :companyId
```

### Example for a Use resource belonging to a company:

```php
<?php

#[ApiResource("/companies/{companyId}/users/{id}", uriVariables: [
'companyId' => [
'class' => Company::class,
'identifiers' => ['id'],
'property' => 'company' // represents the property of User that has the relation to Company
],
'id' => [
'class' => User::class,
'identifiers' => ['id']
]
])]
class User {
#[ApiProperty(identifier=true)]
public $id;
public Company $company;
}
```

```php
<?php

#[ApiResource]
class Company {
#[ApiProperty(identifier=true)]
public $id;
}
```

Generated DQL:

```sql
SELECT * FROM User::class u
JOIN Company::class c ON c.user = u.id AND c.id = :companyId
JOIN u.company c
WHERE u.id = :id AND c.id = :companyId
```

### Example using the inversed relation (get the User's company):

```php
<?php

#[ApiResource]
class User {
#[ApiProperty(identifier=true)]
public $id;
public Company $company;
}
```

```php
<?php

#[ApiResource("/users/{userId}/company", uriVariables: [
'userId' => [
'class' => User::class,
'identifiers' => ['id'],
'property' => 'users' // represents the property users that links Company to User
]
])]
class Company {
#[ApiProperty(identifier=true)]
public $id;
public User[] $users;
}
```

Generated DQL:

```sql
SELECT * FROM Company::class c
JOIN c.users u
WHERE u.id = :id
```

Note what about using the inversed property? This would work but the link with the Resource in unsure.
```sql
SELECT * FROM Company::class c
JOIN User::class u WITH u.companyId = c.id
WHERE u.id = :id
```

### Example to get the users behind a company:

```php
<?php

#[ApiResource("/companies/{companyId}/users", collection: true, uriVariables: [
'companyId' => [
'class' => Company::class,
'identifiers' => ['id'],
'property' => 'company' // Property of User that links to Company
]
])]
class User {
#[ApiProperty(identifier=true)]
public $id;
public Company $company;
}
```

```php
<?php

#[ApiResource]
class Company {
#[ApiProperty(identifier=true)]
public $id;
}
```

Generated DQL:

```sql
SELECT * FROM User::class u
JOIN u.company c
WHERE c.id = :companyId
```

## Links

* Supersedes the [0001-resource-identifiers](0001-resource-identifiers.md) ADR.
Expand Down

0 comments on commit a998b5f

Please sign in to comment.