Skip to content

Multiple errors from one resolver #207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
enumag opened this issue Dec 7, 2017 · 5 comments
Closed

Multiple errors from one resolver #207

enumag opened this issue Dec 7, 2017 · 5 comments

Comments

@enumag
Copy link
Contributor

enumag commented Dec 7, 2017

When resolving a mutation it can very easily result in multiple errors - especially validation of the user input. For example let's say I have a mutation like this:

mutation {
  createPerson(name: "", age: 4) {
    name
    age
  }
}

The resolver for createPerson should add two errors to the result:

  1. Name cannot not be empty.
  2. Age has to be >= 18.

By throwing an exception implementing GraphQL\Error\ClientAware interface I can only add one error to the result. How can I add two (or more)?

@enumag
Copy link
Contributor Author

enumag commented Dec 7, 2017

If this is not supported, please give me some tips how to implement it and I'll send a PR.

@vladar
Copy link
Member

vladar commented Dec 7, 2017

You have at least couple options:

  1. Since these errors are domain errors vs GraphQL errors - model them in your schema. See Validate arguments #97 (comment) and related discussion.

  2. Collect all errors in your resolver, throw a custom exception with those errors attached and then add entries for each of your errors manually using custom error handling, for example:

'resolve' => function($_, $args) {
    $errors = [];
    if (empty($args['name'])) {
        $errors[] = 'Name could not be empty';
    }
    if ($args['age'] < 18) {
        $errors[] = 'Age has to be 18+';
    }
    if (!empty($errors)) {
        $e = new MyValidationException();
        $e->myErrors = $errors;
        throw $e;
    }
}

Then in custom error handler:

$myErrorHandler = function(array $exceptions) {
    $errors = [];
    foreach ($exceptions as $exception) {
        if ($exception->getPrevious() instanceof MyValidationException) {
            foreach ($exception->getPrevious()->myErrors as $message) {
                $errors[] = [/* Format the error as you want */];
            }
        } else {
            $errors[] = [/* Format the error as you want */];
        }
    }
    return $errors;
};

$result = GraphQL::executeQuery(/* $args */)
    ->setErrorsHandler($myErrorHandler)
    ->toArray(); 

@vladar
Copy link
Member

vladar commented Dec 8, 2017

Oh yeah, and one more option I keep forgetting about is to return an array of exceptions from your resolver (vs throwing them).

But that's not certain. I remember that we discussed it at some point, just don't remember if it is actually implemented %) so try it yourself.

@vladar vladar closed this as completed Dec 9, 2017
@enumag
Copy link
Contributor Author

enumag commented Dec 12, 2017

Thank you! Very helpful answer. After some hacking with Overblog/GraphQLBundle I managed to successfully use my own error handler. The problem now is that I want to use the default handler in most cases (such as syntax errors in the GraphQL query) and only use the customized one for some of my own exception. Any tip how I can re-use the default handler?

@enumag
Copy link
Contributor Author

enumag commented Dec 13, 2017

Ok I think I solved that on my own. Posting it here for anyone else looking for the same thing.

		$defaultFormatter = FormattedError::prepareFormatter(null, $debugMode);

		$executionResult->setErrorFormatter(
			function (\Throwable $exception) use ($defaultFormatter, $debugMode) {
				if ($exception->getPrevious() instanceof MyException) {
					return $this->formatException($exception->getPrevious(), $debugMode);
				}

				return $defaultFormatter($exception);
			}
		);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants