Skip to content

Commit d0db326

Browse files
committed
Adding PHP 8 attribute samples to the documentation
1 parent abe0f3a commit d0db326

27 files changed

+1419
-47
lines changed

docs/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ title: Changelog
44
sidebar_label: Changelog
55
---
66

7+
## 4.1
8+
9+
New features:
10+
11+
- All annotations can now be accessed as PHP 8 attributes
12+
13+
714
## 4.0
815

916
This is a complete refactoring from 3.x. While existing annotations are kept compatible, the internals have completely

docs/annotations_reference.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ title: Annotations reference
44
sidebar_label: Annotations reference
55
---
66

7+
Note: all annotations are available both in a Doctrine annotation format (`@Query`) and in PHP 8 attribute format (`#[Query]`).
8+
See [Doctrine annotations vs PHP 8 attributes](doctrine_annotations_attributes.md) for more details.
9+
710
## @Query annotation
811

912
The `@Query` annotation is used to declare a GraphQL query.
@@ -74,7 +77,7 @@ Attribute | Compulsory | Type | Definition
7477
name | *yes* | string | The name of the field.
7578
[outputType](custom_types.md) | *no* | string | Forces the GraphQL output type of the field. Otherwise, return type is used.
7679
phpType | *no* | string | The PHP type of the field (as you would write it in a Docblock)
77-
annotations | *no* | array<Annotations> | A set of annotations that apply to this field. You would typically used a "@Logged" or "@Right" annotation here.
80+
annotations | *no* | array<Annotations> | A set of annotations that apply to this field. You would typically used a "@Logged" or "@Right" annotation here. Available in Doctrine annotations only (not available in the #SourceField PHP 8 attribute)
7881

7982
**Note**: `outputType` and `phpType` are mutually exclusive.
8083

@@ -89,7 +92,7 @@ Attribute | Compulsory | Type | Definition
8992
name | *yes* | string | The name of the field.
9093
[outputType](custom_types.md) | *no*(*) | string | The GraphQL output type of the field.
9194
phpType | *no*(*) | string | The PHP type of the field (as you would write it in a Docblock)
92-
annotations | *no* | array<Annotations> | A set of annotations that apply to this field. You would typically used a "@Logged" or "@Right" annotation here.
95+
annotations | *no* | array<Annotations> | A set of annotations that apply to this field. You would typically used a "@Logged" or "@Right" annotation here. Available in Doctrine annotations only (not available in the #MagicField PHP 8 attribute)
9396

9497
(*) **Note**: `outputType` and `phpType` are mutually exclusive. You MUST provide one of them.
9598

docs/argument_resolving.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ As an example, GraphQLite uses *parameter middlewares* internally to:
1515
- Inject the Webonyx GraphQL resolution object when you type-hint on the `ResolveInfo` object. For instance:
1616
```php
1717
/**
18-
* @Query
1918
* @return Product[]
2019
*/
20+
#[Query]
2121
public function products(ResolveInfo $info): array
2222
```
2323
In the query above, the `$info` argument is filled with the Webonyx `ResolveInfo` class thanks to the
@@ -58,14 +58,19 @@ If you plan to use annotations while resolving arguments, your annotation should
5858

5959
For instance, if we want GraphQLite to inject a service in an argument, we can use `@Autowire(for="myService")`.
6060

61+
For PHP 8 attributes, we only need to put declare the annotation can target parameters: `#[Attribute(Attribute::TARGET_PARAMETER)]`.
62+
6163
The annotation looks like this:
6264

6365
```php
66+
use Attribute;
67+
6468
/**
6569
* Use this annotation to autowire a service from the container into a given parameter of a field/query/mutation.
6670
*
6771
* @Annotation
6872
*/
73+
#[Attribute(Attribute::TARGET_PARAMETER)]
6974
class Autowire implements ParameterAnnotationInterface
7075
{
7176
/**

docs/authentication_authorization.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,30 @@ See <a href="implementing-security.md">Connecting GraphQLite to your framework's
2222
## `@Logged` and `@Right` annotations
2323

2424
GraphQLite exposes two annotations (`@Logged` and `@Right`) that you can use to restrict access to a resource.
25+
<!--DOCUSAURUS_CODE_TABS-->
26+
<!--PHP 8+-->
27+
```php
28+
namespace App\Controller;
2529

30+
use TheCodingMachine\GraphQLite\Annotations\Query;
31+
use TheCodingMachine\GraphQLite\Annotations\Logged;
32+
use TheCodingMachine\GraphQLite\Annotations\Right;
33+
34+
class UserController
35+
{
36+
/**
37+
* @return User[]
38+
*/
39+
#[Query]
40+
#[Logged]
41+
#[Right("CAN_VIEW_USER_LIST")]
42+
public function users(int $limit, int $offset): array
43+
{
44+
// ...
45+
}
46+
}
47+
```
48+
<!--PHP 7+-->
2649
```php
2750
namespace App\Controller;
2851

@@ -44,6 +67,8 @@ class UserController
4467
}
4568
}
4669
```
70+
<!--END_DOCUSAURUS_CODE_TABS-->
71+
4772

4873
In the example above, the query `users` will only be available if the user making the query is logged AND if he
4974
has the `CAN_VIEW_USER_LIST` right.
@@ -62,6 +87,28 @@ If you do not want an error to be thrown when a user attempts to query a field/q
6287

6388
The `@FailWith` annotation contains the value that will be returned for users with insufficient rights.
6489

90+
<!--DOCUSAURUS_CODE_TABS-->
91+
<!--PHP 8+-->
92+
```php
93+
class UserController
94+
{
95+
/**
96+
* If a user is not logged or if the user has not the right "CAN_VIEW_USER_LIST",
97+
* the value returned will be "null".
98+
*
99+
* @return User[]
100+
*/
101+
#[Query]
102+
#[Logged]
103+
#[Right("CAN_VIEW_USER_LIST")]
104+
#[FailWith(null)]
105+
public function users(int $limit, int $offset): array
106+
{
107+
// ...
108+
}
109+
}
110+
```
111+
<!--PHP 7+-->
65112
```php
66113
class UserController
67114
{
@@ -81,11 +128,37 @@ class UserController
81128
}
82129
}
83130
```
131+
<!--END_DOCUSAURUS_CODE_TABS-->
84132

85133
## Injecting the current user as a parameter
86134

87135
Use the `@InjectUser` annotation to get an instance of the current user logged in.
88136

137+
<!--DOCUSAURUS_CODE_TABS-->
138+
<!--PHP 8+-->
139+
```php
140+
namespace App\Controller;
141+
142+
use TheCodingMachine\GraphQLite\Annotations\Query;
143+
use TheCodingMachine\GraphQLite\Annotations\InjectUser;
144+
145+
class ProductController
146+
{
147+
/**
148+
* @Query
149+
* @return Product
150+
*/
151+
public function product(
152+
int $id,
153+
#[InjectUser]
154+
User $user
155+
): Product
156+
{
157+
// ...
158+
}
159+
}
160+
```
161+
<!--PHP 7+-->
89162
```php
90163
namespace App\Controller;
91164

@@ -105,6 +178,7 @@ class ProductController
105178
}
106179
}
107180
```
181+
<!--END_DOCUSAURUS_CODE_TABS-->
108182

109183
The `@InjectUser` annotation can be used next to:
110184

@@ -123,6 +197,29 @@ Some will be available to him and some won't.
123197
If you want to add an extra level of security (or if you want your schema to be kept secret to unauthorized users),
124198
you can use the `@HideIfUnauthorized` annotation.
125199

200+
<!--DOCUSAURUS_CODE_TABS-->
201+
<!--PHP 8+-->
202+
```php
203+
class UserController
204+
{
205+
/**
206+
* If a user is not logged or if the user has not the right "CAN_VIEW_USER_LIST",
207+
* the schema will NOT contain the "users" query at all (so trying to call the
208+
* "users" query will result in a GraphQL "query not found" error.
209+
*
210+
* @return User[]
211+
*/
212+
#[Query]
213+
#[Logged]
214+
#[Right("CAN_VIEW_USER_LIST")]
215+
#[HideIfUnauthorized]
216+
public function users(int $limit, int $offset): array
217+
{
218+
// ...
219+
}
220+
}
221+
```
222+
<!--PHP 7+-->
126223
```php
127224
class UserController
128225
{
@@ -143,6 +240,7 @@ class UserController
143240
}
144241
}
145242
```
243+
<!--END_DOCUSAURUS_CODE_TABS-->
146244

147245
While this is the most secured mode, it can have drawbacks when working with development tools
148246
(you need to be logged as admin to fetch the complete schema).

docs/autowiring.md

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,33 @@ the service instance.
1717
Let's assume you are running an international store. You have a `Product` class. Each product has many names (depending
1818
on the language of the user).
1919

20+
<!--DOCUSAURUS_CODE_TABS-->
21+
<!--PHP 8+-->
22+
```php
23+
namespace App\Entities;
24+
25+
use TheCodingMachine\GraphQLite\Annotations\Autowire;
26+
use TheCodingMachine\GraphQLite\Annotations\Field;
27+
use TheCodingMachine\GraphQLite\Annotations\Type;
28+
29+
use Symfony\Component\Translation\TranslatorInterface;
30+
31+
#[Type]
32+
class Product
33+
{
34+
// ...
35+
36+
#[Field]
37+
public function getName(
38+
#[Autowire]
39+
TranslatorInterface $translator
40+
): string
41+
{
42+
return $translator->trans('product_name_'.$this->id);
43+
}
44+
}
45+
```
46+
<!--PHP 7+-->
2047
```php
2148
namespace App\Entities;
2249

@@ -43,6 +70,7 @@ class Product
4370
}
4471
}
4572
```
73+
<!--END_DOCUSAURUS_CODE_TABS-->
4674

4775
When GraphQLite queries the name, it will automatically fetch the translator service.
4876

@@ -59,10 +87,8 @@ with a particular service implementation. This makes your code tightly coupled a
5987
<div class="alert alert-error">
6088
Please don't do that:
6189

62-
<pre><code> /**
63-
* @Field()
64-
*/
65-
public function getName(MyTranslator $translator): string
90+
<pre><code> #[Field]
91+
public function getName(#[Autowire] MyTranslator $translator): string
6692
{
6793
// Your domain is suddenly tightly coupled to the MyTranslator class.
6894
}
@@ -74,10 +100,8 @@ Instead, be sure to type-hint against an interface.
74100
<div class="alert alert-success">
75101
Do this instead:
76102

77-
<pre><code> /**
78-
* @Field()
79-
*/
80-
public function getName(TranslatorInterface $translator): string
103+
<pre><code> #[Field]
104+
public function getName(#[Autowire] TranslatorInterface $translator): string
81105
{
82106
// Good. You can switch translator implementation any time.
83107
}
@@ -90,11 +114,18 @@ By type-hinting against an interface, your code remains testable and is decouple
90114

91115
Optionally, you can specify the identifier of the service you want to fetch from the controller:
92116

117+
<!--DOCUSAURUS_CODE_TABS-->
118+
<!--PHP 8+-->
119+
```php
120+
#[Autowire(identifier: "translator")]
121+
```
122+
<!--PHP 7+-->
93123
```php
94124
/**
95125
* @Autowire(for="$translator", identifier="translator")
96126
*/
97127
```
128+
<!--END_DOCUSAURUS_CODE_TABS-->
98129

99130
<div class="alert alert-error">While GraphQLite offers the possibility to specify the name of the service to be
100131
autowired, we would like to emphasize that this is <strong>highly discouraged</strong>. Hard-coding a container

docs/custom_types.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,36 @@ In some special cases, you want to override the GraphQL return type that is attr
88

99
For instance:
1010

11+
<!--DOCUSAURUS_CODE_TABS-->
12+
<!--PHP 8+-->
13+
```php
14+
#[Type(class: Product::class)]
15+
class ProductType
16+
{
17+
#[Field]
18+
public function getId(Product $source): string
19+
{
20+
return $source->getId();
21+
}
22+
}
23+
```
24+
<!--PHP 7+-->
1125
```php
1226
/**
1327
* @Type(class=Product::class)
1428
*/
1529
class ProductType
1630
{
1731
/**
18-
* @Field(name="id")
32+
* @Field
1933
*/
2034
public function getId(Product $source): string
2135
{
2236
return $source->getId();
2337
}
2438
}
2539
```
40+
<!--END_DOCUSAURUS_CODE_TABS-->
2641

2742
In the example above, GraphQLite will generate a GraphQL schema with a field `id` of type `string`:
2843

@@ -37,11 +52,18 @@ is an `ID` or not.
3752

3853
You can help GraphQLite by manually specifying the output type to use:
3954

55+
<!--DOCUSAURUS_CODE_TABS-->
56+
<!--PHP 8+-->
57+
```php
58+
#[Field(outputType: "ID")]
59+
```
60+
<!--PHP 7+-->
4061
```php
4162
/**
4263
* @Field(name="id", outputType="ID")
4364
*/
4465
```
66+
<!--END_DOCUSAURUS_CODE_TABS-->
4567

4668
## Usage
4769

0 commit comments

Comments
 (0)