mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-22 04:46:04 +03:00
Work in progress on better docs (added section on query execution and error handling)
This commit is contained in:
parent
24b2285ffe
commit
ccad34517c
136
docs/error-handling.md
Normal file
136
docs/error-handling.md
Normal file
@ -0,0 +1,136 @@
|
||||
# Errors in GraphQL
|
||||
|
||||
Query execution process never throws exceptions. Instead all errors that occur during query execution
|
||||
are caught, collected and included in response.
|
||||
|
||||
There are 3 types of errors in GraphQL (Syntax, Validation and Execution errors):
|
||||
|
||||
**Syntax** errors are returned in response when query has invalid syntax and could not be parsed.
|
||||
Example output for invalid query `{hello` (missing bracket):
|
||||
```php
|
||||
[
|
||||
'errors' => [
|
||||
[
|
||||
'message' => "Syntax Error GraphQL request (1:7) Expected Name, found <EOF>\n\n1: {hello\n ^\n",
|
||||
'locations' => [
|
||||
['line' => 1, 'column' => 7]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
**Validation** errors - returned in response when query has semantic errors.
|
||||
Example output for invalid query `{unknownField}`:
|
||||
```php
|
||||
[
|
||||
'errors' => [
|
||||
[
|
||||
'message' => 'Cannot query field "unknownField" on type "Query".',
|
||||
'locations' => [
|
||||
['line' => 1, 'column' => 2]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
**Execution** errors - included in response when some field resolver throws
|
||||
(or returns unexpected value). Example output for query with exception thrown in
|
||||
field resolver `{fieldWithException}`:
|
||||
```php
|
||||
[
|
||||
'data' => [
|
||||
'fieldWithException' => null
|
||||
],
|
||||
'errors' => [
|
||||
[
|
||||
'message' => 'Exception message thrown in field resolver',
|
||||
'locations' => [
|
||||
['line' => 1, 'column' => 2]
|
||||
],
|
||||
'path': [
|
||||
'fieldWithException'
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
Obviously when **Syntax** or **Validation** error is detected - process is interrupted and query is not
|
||||
executed. In such scenarios response only contains **errors**, but not **data**.
|
||||
|
||||
GraphQL is forgiving to **Execution** errors which occur in resolvers of nullable fields.
|
||||
If such field throws or returns unexpected value the value of the field in response will be simply
|
||||
replaced with `null` and error entry will be added to response.
|
||||
|
||||
If exception is thrown in non-null field - it will be bubbled up to first nullable field which will
|
||||
be replaced with `null` (and error entry added to response). If all fields up to the root are non-null
|
||||
**data** entry will be missing in response and only **errors** key will be presented.
|
||||
|
||||
# Debugging tools
|
||||
|
||||
Each error entry contains pointer to line and column in original query string which caused
|
||||
the error:
|
||||
|
||||
```php
|
||||
'locations' => [
|
||||
['line' => 1, 'column' => 2]
|
||||
]
|
||||
```
|
||||
|
||||
GraphQL clients like **Relay** or **GraphiQL** leverage this information to highlight
|
||||
actual piece of query containing error.
|
||||
|
||||
In some cases (like deep fragment fields) locations will include several entries to track down the
|
||||
path to field with error in query.
|
||||
|
||||
**Execution** errors also contain **path** from the very root field to actual field value producing
|
||||
an error (including indexes for array types and fieldNames for object types). So in complex situation
|
||||
this path could look like this:
|
||||
|
||||
```php
|
||||
'path' => [
|
||||
'lastStoryPosted',
|
||||
'author',
|
||||
'friends',
|
||||
3
|
||||
'fieldWithException'
|
||||
]
|
||||
```
|
||||
|
||||
# Custom Error Formatting
|
||||
|
||||
If you want to apply custom formatting to errors - use **GraphQL::executeAndReturnResult()** instead
|
||||
of **GraphQL::execute()**.
|
||||
|
||||
It has exactly the same [signature](executing-queries/), but instead of array it
|
||||
returns `GraphQL\Executor\ExecutionResult` instance which holds errors in public **$errors**
|
||||
property and data in **$data** property.
|
||||
|
||||
Each entry of **$errors** array contains instance of `GraphQL\Error\Error` which wraps original
|
||||
exceptions thrown by resolvers. To access original exceptions use `$error->getPrevious()` method.
|
||||
But note that previous exception is only available for **Execution** errors.
|
||||
|
||||
# Schema Errors
|
||||
We only covered errors which occur during query execution process. But schema definition can also
|
||||
throw if there is an error in one of type definitions.
|
||||
|
||||
Usually such errors mean that there is some logical error in your schema and it is the only case
|
||||
when it makes sense to return `500` error code for GraphQL endpoint:
|
||||
|
||||
```php
|
||||
try {
|
||||
$schema = new Schema([
|
||||
// ...
|
||||
]);
|
||||
|
||||
$result = GraphQL::execute($schema, $query);
|
||||
} catch(\Exception $e) {
|
||||
header('Content-Type: application/json', true, 500);
|
||||
echo json_encode([
|
||||
'message' => 'Unexpected error'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
```
|
49
docs/executing-queries.md
Normal file
49
docs/executing-queries.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Overview
|
||||
Query execution is a complex process involving multiple steps, including query **parsing**,
|
||||
**validating** and finally **executing** against your schema.
|
||||
|
||||
**graphql-php** provides convenient facade for this process in class `GraphQL\GraphQL`:
|
||||
|
||||
```php
|
||||
use GraphQL\GraphQL;
|
||||
|
||||
$result = GraphQL::execute(
|
||||
$schema,
|
||||
$queryString,
|
||||
$rootValue = null,
|
||||
$contextValue = null,
|
||||
$variableValues = null,
|
||||
$operationName = null
|
||||
);
|
||||
```
|
||||
|
||||
Method returns `array` with **data** and **errors** keys, as described by
|
||||
[GraphQL specs](http://facebook.github.io/graphql/#sec-Response-Format).
|
||||
This array is suitable for further serialization (e.g. using `json_encode`).
|
||||
See also section on [error handling](error-handling/).
|
||||
|
||||
|
||||
Description of method arguments:
|
||||
|
||||
Argument | Type | Notes
|
||||
------------ | -------- | -----
|
||||
schema | `GraphQL\Schema` | **Required.** Instance of your application [Schema](type-system/schema/)
|
||||
queryString | `string` or `GraphQL\Language\AST\Document` | **Required.** Actual GraphQL query string to be parsed, validated and executed. If you parse query elsewhere before executing - pass corresponding ast document here to avoid new parsing.
|
||||
rootValue | `mixed` | Any value that represents a root of your data graph. It is passed as 1st argument to field resolvers of [Query type](type-system/schema/#query-and-mutation-types). Can be omitted or set to null if actual root values are fetched by Query type itself.
|
||||
contextValue | `mixed` | Any value that holds information shared between all field resolvers. Most often they use it to pass currently logged in user, locale details, etc.<br><br>It will be available as 3rd argument in all field resolvers. (see section on [Field Definitions](type-system/object-types/#field-configuration-options) for reference) **graphql-php** never modifies this value and passes it *as is* to all underlying resolvers.
|
||||
variableValues | `array` | Map of variable values passed along with query string. See section on [query variables on official GraphQL website](http://graphql.org/learn/queries/#variables)
|
||||
operationName | `string` | Allows the caller to specify which operation in queryString will be run, in cases where queryString contains multiple top-level operations.
|
||||
|
||||
Following reading describes implementation details of query execution process. It may clarify some
|
||||
internals of GraphQL but is not required in order to use it. Feel free to skip to next section
|
||||
on [Error Handling](error-handling/) for essentials.
|
||||
|
||||
|
||||
# Parsing
|
||||
TODOC
|
||||
|
||||
# Validating
|
||||
TODOC
|
||||
|
||||
# Executing
|
||||
TODOC
|
@ -1,6 +1,6 @@
|
||||
# Built-in directives
|
||||
Directive is a way to dynamically change the structure and shape of queries using variables.
|
||||
Directive can be attached to a field or fragment inclusion, and can affect execution of the
|
||||
Directive is a way for client to give GraphQL server additional context and hints on how to execute
|
||||
the query. Directive can be attached to a field or fragment inclusion, and can affect execution of the
|
||||
query in any way the server desires.
|
||||
|
||||
GraphQL specification includes two built-in directives:
|
||||
@ -21,7 +21,7 @@ query Hero($episode: Episode, $withFriends: Boolean!) {
|
||||
```
|
||||
Here if `$withFriends` variable is set to `false` - friends section will be ignored and excluded
|
||||
from response. Important implementation detail: those fields will never be executed
|
||||
(and not just removed from response after execution).
|
||||
(not just removed from response after execution).
|
||||
|
||||
# Custom directives
|
||||
**graphql-php** supports custom directives even though their presence does not affect execution of fields.
|
||||
|
@ -50,6 +50,12 @@ class QueryType extends BaseType
|
||||
'type' => Types::string(),
|
||||
'deprecationReason' => 'This field is deprecated!'
|
||||
],
|
||||
'fieldWithException' => [
|
||||
'type' => Types::string(),
|
||||
'resolve' => function() {
|
||||
throw new \Exception("Exception message thrown in field resolver");
|
||||
}
|
||||
],
|
||||
'hello' => Type::string()
|
||||
],
|
||||
'resolveField' => function($val, $args, $context, ResolveInfo $info) {
|
||||
|
@ -46,9 +46,7 @@ try {
|
||||
$data += ['query' => null, 'variables' => null];
|
||||
|
||||
if (null === $data['query']) {
|
||||
$data['query'] = '
|
||||
{hello}
|
||||
';
|
||||
$data['query'] = '{hello}';
|
||||
}
|
||||
|
||||
// GraphQL schema to be passed to query executor:
|
||||
|
@ -13,7 +13,9 @@ pages:
|
||||
- Input Types: type-system/input-types.md
|
||||
- Directives: type-system/directives.md
|
||||
- Defining Schema: type-system/schema.md
|
||||
- Data Fetching: data-fetching.md
|
||||
- Executing Queries: executing-queries.md
|
||||
- Handling Errors: error-handling.md
|
||||
- Fetching Data: data-fetching.md
|
||||
- Best Practices: best-practices.md
|
||||
- Complementary Tools: complementary-tools.md
|
||||
theme: readthedocs
|
||||
|
Loading…
Reference in New Issue
Block a user