Skip to content

Commit 0fe6e60

Browse files
committed
Upgrade attribute type option system
Introducing: - NullableType: allows to overwrite nullable class types as well - ListType: allows to define lists
1 parent 5860c16 commit 0fe6e60

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+615
-362
lines changed

docs/todo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ This library is still work in progress, and misses some valuable features:
33

44
- Introduction of `#[Deprecated]` attribute
55
- ~~Overwrite type via attributes~~
6-
- Allow simple lists (array type)
6+
- ~~Allow simple lists (array type)~~
77
- Connection, edge, nodes (see https://relay.dev/graphql/connections.htm)
88
- Make AST serializable (cacheable)
99
- Handle `DateTime` and `DateTimeImmutable`

docs/usage.md

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
# Usage
2+
At minimum, a query and mutation needs to be defined to build a valid schema.
23

4+
## Attributes
35
The following attributes can be used:
46

57
- `#[Mutation]`
68
- `#[Query]`
79
- `#[InputType]`
810
- `#[Type]`
911
- `#[Enum]`
10-
- `#[EnumValue]`
12+
- `#[EnumValue]`
1113
- `#[Field]`
1214
- `#[Arg]`
1315

1416
See below for more information about each attribute:
1517

16-
## Mutation and query
18+
### Mutation and query
1719

1820
Mutations and queries can be defined with `#[Mutation]` and `#[Query]`. In order to configure your class as mutation or
1921
query, just add these attributes on class level:
@@ -35,7 +37,7 @@ final readonly YourQuery
3537
}
3638
```
3739

38-
### Automatic schema creation
40+
#### Automatic schema creation
3941

4042
*GraphQL Attribute Schema* will read the available public method's signature: input arguments and output type. These
4143
will be automatically configured in the schema (this can be overwritten by using `#[Arg]`, see [Arg](#arg) section).
@@ -47,7 +49,7 @@ When using objects, make sure these are defined as well with `#[InputType]` for
4749
Also, the name of the mutation or query will be automatically read from the class name (this can be overwritten, see
4850
options).
4951

50-
### Requirements
52+
#### Requirements
5153

5254
Mutations and queries:
5355

@@ -57,18 +59,17 @@ Mutations and queries:
5759
with `#[Autoconfigure(public: true)]`),
5860
- must have only one *public* method (apart from `__construct`), which will be called on resolve.
5961

60-
### Options
62+
#### Options
6163

6264
Both `#[Mutation]` and `#[Query]` attribute can be configured:
6365

64-
| Option | Description |
65-
|---------------|-------------------------------------------------------------------------------|
66-
| `name` | Set custom name of mutation or query (instead of based on class) |
67-
| `description` | Set description of the mutation or query, readable in the GraphQL schema |
68-
| `type` | Set custom return type; can be either a `#[Type]` FQCN or `ScalarType` (enum) |
69-
| `isRequired` | When a custom type is set, isRequired should be set as well |
66+
| Option | Description |
67+
|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
68+
| `name` | Set custom name of mutation or query (instead of based on class) |
69+
| `description` | Set description of the mutation or query, readable in the GraphQL schema |
70+
| `type` | Set custom return type; it can be:<br/>- A Type (FQCN)<br/>- A `ScalarType` (e.g. `ScalarType::Int`)<br/>- A `ListType` (e.g. `new ListType(ScalarType::Int)`)<br/>- A `NullableType` (e.g. `new NullableType(SomeType::class)`)<br/>- A combination of `ListType` and `NullableType` and a Type FQCN or `ScalarType` <br/>(e.g. `new NullableType(new ListType(ScalarType::String))`) |
7071

71-
## InputType
72+
### InputType
7273

7374
Input types can be defined with `#[InputType]`.
7475
In order to configure your class as input type, just add this attribute on class level:
@@ -93,7 +94,7 @@ final readonly class YourInputType
9394
}
9495
```
9596

96-
### Automatic schema creation
97+
#### Automatic schema creation
9798

9899
*GraphQL Attribute Schema* will read the `__construct` signature: input arguments.
99100
Any input argument with a defined `#[Field]` will be automatically configured in the schema (this can be overwritten,
@@ -105,7 +106,7 @@ When using objects, make sure these are defined as well with `#[InputType]` or `
105106
Also, the name of the input type will be automatically read from the class name (this can be overwritten, see
106107
options).
107108

108-
### Options
109+
#### Options
109110

110111
`#[InputType]` attribute can be configured:
111112

@@ -114,7 +115,7 @@ options).
114115
| `name` | Set custom name of input type (instead of based on class) |
115116
| `description` | Set description of the input type, readable in the GraphQL schema |
116117

117-
## Type
118+
### Type
118119

119120
Types can be defined with `#[Type]`.
120121
In order to configure your class as type, just add this attribute on class level:
@@ -145,7 +146,7 @@ final readonly class YourType
145146
}
146147
```
147148

148-
### Automatic schema creation
149+
#### Automatic schema creation
149150

150151
*GraphQL Attribute Schema* will both read the `__construct` signature: input arguments, as well as read all methods.
151152

@@ -163,7 +164,7 @@ When using objects, make sure these are defined as well with `#[InputType]` or `
163164
Also, the name of the type will be automatically read from the class name (this can be overwritten, see
164165
options).
165166

166-
### Options
167+
#### Options
167168

168169
`#[Type]` attribute can be configured:
169170

@@ -172,7 +173,7 @@ options).
172173
| `name` | Set custom name of type (instead of based on class) |
173174
| `description` | Set description of the type, readable in the GraphQL schema |
174175

175-
## Enum
176+
### Enum
176177

177178
Enums can be defined with `#[Enum]`.
178179
In order to configure your enum class as enum, just add this attribute on class level:
@@ -191,22 +192,22 @@ enum YourEnumType: string
191192
}
192193
```
193194

194-
### Automatic schema creation
195+
#### Automatic schema creation
195196

196197
*GraphQL Attribute Schema* will read the enum signature.
197198

198199
The values for the enum will be automatically read from the PHP `enum`; it uses the string version.
199200

200201
The name of the enum will be automatically read from the class name (this can be overwritten, see options).
201202

202-
### Requirements
203+
#### Requirements
203204

204205
Enums:
205206

206207
- must be of the PHP native `enum` type (no classes with public constants)
207208
- The PHP `enum` type must be a `BackedEnum`
208209

209-
### Options
210+
#### Options
210211

211212
`#[Enum]` attribute can be configured:
212213

@@ -223,7 +224,7 @@ Each case in the `enum` type can be configured as well, with the `#[EnumValue]`
223224
|---------------|------------------------------------------------------------------|
224225
| `description` | Set description of the enum case, readable in the GraphQL schema |
225226

226-
## Field
227+
### Field
227228

228229
In `#[Type]` and `#[InputType]`, to define fields, the `#[Field]` attribute can be used.
229230
In order to configure any fields this can be set on constructor property (for `#[InputType]` or `#[Type]`) or
@@ -268,18 +269,17 @@ final readonly class YourInputType
268269
}
269270
```
270271

271-
### Options
272+
#### Options
272273

273274
`#[Field]` attribute can be configured:
274275

275-
| Option | Description |
276-
|---------------|----------------------------------------------------------------------------------------|
277-
| `name` | Set custom name of field (instead of based on class) |
278-
| `description` | Set description of the field, readable in the GraphQL schema |
279-
| `type` | Set custom type; can be either a `#[Type]`, `#[InputType]` FQCN or `ScalarType` (enum) |
280-
| `isRequired` | When a custom type is set, isRequired should be set as well |
276+
| Option | Description |
277+
|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
278+
| `name` | Set custom name of field (instead of based on class) |
279+
| `description` | Set description of the field, readable in the GraphQL schema |
280+
| `type` | Set custom return type; it can be:<br/>- A Type (FQCN)<br/>- A `ScalarType` (e.g. `ScalarType::Int`)<br/>- A `ListType` (e.g. `new ListType(ScalarType::Int)`)<br/>- A `NullableType` (e.g. `new NullableType(SomeType::class)`)<br/>- A combination of `ListType` and `NullableType` and a Type FQCN or `ScalarType` <br/>(e.g. `new NullableType(new ListType(ScalarType::String))`) |
281281

282-
## Arg
282+
### Arg
283283

284284
For `#[Mutation]`, `#[Query]` and `#[Type]` methods defined with `#[Field]`, input arguments are read
285285
automatically from the signature.
@@ -327,13 +327,12 @@ final readonly class YourType
327327
}
328328
```
329329

330-
### Options
330+
#### Options
331331

332332
`#[Arg]` attribute can be configured:
333333

334-
| Option | Description |
335-
|---------------|------------------------------------------------------------------------|
336-
| `name` | Set custom name of argument (instead of based on class) |
337-
| `description` | Set description of the argument, readable in the GraphQL schema |
338-
| `type` | Set custom type; can be either a `#[Type]` FQCN or `ScalarType` (enum) |
339-
| `isRequired` | When a custom type is set, isRequired should be set as well |
334+
| Option | Description |
335+
|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
336+
| `name` | Set custom name of argument (instead of based on class) |
337+
| `description` | Set description of the argument, readable in the GraphQL schema |
338+
| `type` | Set custom return type; it can be:<br/>- A Type (FQCN)<br/>- A `ScalarType` (e.g. `ScalarType::Int`)<br/>- A `ListType` (e.g. `new ListType(ScalarType::Int)`)<br/>- A `NullableType` (e.g. `new NullableType(SomeType::class)`)<br/>- A combination of `ListType` and `NullableType` and a Type FQCN or `ScalarType` <br/>(e.g. `new NullableType(new ListType(ScalarType::String))`) |

src/Attribute/Arg.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66

77
use Attribute;
88
use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
9+
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;
910

1011
#[Attribute(Attribute::TARGET_PARAMETER)]
1112
final readonly class Arg implements BaseAttribute, TypedAttribute
1213
{
1314
/**
14-
* @param class-string|ScalarType|null $type
15+
* @param class-string|Type|ScalarType|null $type
1516
*/
1617
public function __construct(
1718
public ?string $name = null,
1819
public ?string $description = null,
19-
public string|ScalarType|null $type = null,
20-
public bool $isRequired = true,
20+
public string|Type|ScalarType|null $type = null,
2121
) {}
2222

2323
public function getName(): ?string
@@ -30,13 +30,8 @@ public function getDescription(): ?string
3030
return $this->description;
3131
}
3232

33-
public function getType(): string|ScalarType|null
33+
public function getType(): string|Type|ScalarType|null
3434
{
3535
return $this->type;
3636
}
37-
38-
public function isRequired(): bool
39-
{
40-
return $this->isRequired;
41-
}
4237
}

src/Attribute/Field.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66

77
use Attribute;
88
use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
9+
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;
910

1011
#[Attribute(Attribute::TARGET_PROPERTY|Attribute::TARGET_METHOD)]
1112
final readonly class Field implements BaseAttribute, TypedAttribute
1213
{
1314
/**
14-
* @param class-string|ScalarType|null $type
15+
* @param class-string|Type|ScalarType|null $type
1516
*/
1617
public function __construct(
1718
public ?string $name = null,
1819
public ?string $description = null,
19-
public string|ScalarType|null $type = null,
20-
public bool $isRequired = true,
20+
public string|Type|ScalarType|null $type = null,
2121
) {}
2222

2323
public function getName(): ?string
@@ -30,13 +30,8 @@ public function getDescription(): ?string
3030
return $this->description;
3131
}
3232

33-
public function getType(): string|ScalarType|null
33+
public function getType(): string|Type|ScalarType|null
3434
{
3535
return $this->type;
3636
}
37-
38-
public function isRequired(): bool
39-
{
40-
return $this->isRequired;
41-
}
4237
}

src/Attribute/Mutation.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@
66

77
use Attribute;
88
use Jerowork\GraphqlAttributeSchema\Attribute\Option\ScalarType;
9+
use Jerowork\GraphqlAttributeSchema\Attribute\Option\Type;
910

1011
#[Attribute(Attribute::TARGET_CLASS)]
1112
final readonly class Mutation implements BaseAttribute, TypedAttribute
1213
{
1314
/**
14-
* @param class-string|ScalarType|null $type
15+
* @param class-string|Type|ScalarType|null $type
1516
*/
1617
public function __construct(
1718
public ?string $name = null,
1819
public ?string $description = null,
19-
public string|ScalarType|null $type = null,
20-
public bool $isRequired = true,
20+
public string|Type|ScalarType|null $type = null,
2121
) {}
2222

2323
public function getName(): ?string
@@ -30,13 +30,8 @@ public function getDescription(): ?string
3030
return $this->description;
3131
}
3232

33-
public function getType(): string|ScalarType|null
33+
public function getType(): string|Type|ScalarType|null
3434
{
3535
return $this->type;
3636
}
37-
38-
public function isRequired(): bool
39-
{
40-
return $this->isRequired;
41-
}
4237
}

src/Attribute/Option/ListType.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;
6+
7+
final readonly class ListType implements Type
8+
{
9+
/**
10+
* @param class-string|Type|ScalarType $type
11+
*/
12+
public function __construct(
13+
public string|Type|ScalarType $type,
14+
) {}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;
6+
7+
final readonly class NullableType implements Type
8+
{
9+
/**
10+
* @param class-string|Type|ScalarType $type
11+
*/
12+
public function __construct(
13+
public string|Type|ScalarType $type,
14+
) {}
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;
6+
7+
final readonly class ObjectType implements Type
8+
{
9+
/**
10+
* @param class-string $className
11+
*/
12+
public function __construct(
13+
public string $className,
14+
) {}
15+
}

src/Attribute/Option/Type.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jerowork\GraphqlAttributeSchema\Attribute\Option;
6+
7+
interface Type {}

0 commit comments

Comments
 (0)