0

I copied the example that the Lighthouse website links to (https://webonyx.github.io/graphql-php/type-system/scalar-types/) for a custom Email type. (see code below)

Unfortunately, if I now go to the graphql-playground, I get a 500 error stating: "No matching subclass of GraphQL\Type\Definition\ScalarType of found for the scalar Email"

How can I solve this error?

<?php
// file: /graphql/EmailType.php

namespace MyApp;

use GraphQL\Error\Error;
use GraphQL\Error\InvariantViolation;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Type\Definition\ScalarType;
use GraphQL\Utils\Utils;

class EmailType extends ScalarType
{
    // Note: name can be omitted. In this case it will be inferred from class name 
    // (suffix "Type" will be dropped)
    public $name = 'Email';

    /**
     * Serializes an internal value to include in a response.
     *
     * @param string $value
     * @return string
     */
    public function serialize($value)
    {
        // Assuming internal representation of email is always correct:
        return $value;
    }

    /**
     * Parses an externally provided value (query variable) to use as an input
     *
     * @param mixed $value
     * @return mixed
     */
    public function parseValue($value)
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            throw new Error("Cannot represent following value as email: " . Utils::printSafeJson($value));
        }
        return $value;
    }

    /**
     * Parses an externally provided literal value (hardcoded in GraphQL query) to use as an input.
     * 
     * E.g. 
     * {
     *   user(email: "user@example.com") 
     * }
     *
     * @param \GraphQL\Language\AST\Node $valueNode
     * @param array|null $variables
     * @return string
     * @throws Error
     */
    public function parseLiteral($valueNode, array $variables = null)
    {
        // Note: throwing GraphQL\Error\Error vs \UnexpectedValueException to benefit from GraphQL
        // error location in query:
        if (!$valueNode instanceof StringValueNode) {
            throw new Error('Query error: Can only parse strings got: ' . $valueNode->kind, [$valueNode]);
        }
        if (!filter_var($valueNode->value, FILTER_VALIDATE_EMAIL)) {
            throw new Error("Not a valid email", [$valueNode]);
        }
        return $valueNode->value;
    }
}
Hendrik Jan
  • 4,396
  • 8
  • 39
  • 75

1 Answers1

0

(Edit: Look at the comment from Enzo Notario, below, for a real solution)

I fixed this problem in the following way:

Inside 'composer.json' I added the folder 'graphql' (in which the EmailType class file is) to the list of folders in 'autoload':

"autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "classmap": [
            "database/seeds",
            "database/factories",
            "graphql"
        ]
    },

Then I used the following commands (I am quite sure the last line is not needed):

php artisan clear-compiled
composer dumpautoload
composer update

After this al was working as expected.

Hendrik Jan
  • 4,396
  • 8
  • 39
  • 75
  • 2
    It works because with `composer dump-autoload` it "discovers" all classes. But I think that soon or late you will have some troubles (especially in your production env). So I'd recommend you to modify the namespace/path of the scalar so it matches perfectly and just works. For example, you could put it in `App\Graphql\Scalars` (and in the folder `app/Graphql/Scalars`) – Enzo Notario Dec 28 '19 at 12:41
  • I changed the namespace as you suggested. It now works without ```composer dump-autoload```. I did not realize that namespace and filename need to match. Thanks for pointing that out. – Hendrik Jan Dec 29 '19 at 08:49