Lighthouse: Trouble retrieving a date as string - "String cannot represent non scalar value: instance of Illuminate\\Support\\Carbon"

Created on 10 Apr 2018  路  6Comments  路  Source: nuwave/lighthouse

Hey,

I have started building my first project with Lighthouse.

It's amazingly fast way to building apps. Still, I'm running into an issue with retrieving a string Date representation. I have inserted a new enrty into the database through a mutation.

This is the error that gets returned:
"String cannot represent non scalar value: instance of Illuminate\\Support\\Carbon"

Here is the schema file I'm using:

# schema.graphql

type Project {
    id: ID!
    parent_id: Parent @belongsTo
    name: String!
    created_at: String
    updated_at: String
    deleted_at: String
}

type Query {
    projects: [Project!]! @field(resolver: "App\\Http\\GraphQL\\ProjectQueries@index")
}

As can be seen from artisan tinker, the date is present on the data instance:
screen shot 2018-04-10 at 13 57 30

And the screenshot from GraphQL Playground:
screen shot 2018-04-10 at 13 21 24

Am I doing it wrong or is that an issue that needs additional work on your end?

Thank you again for this package & the work you're doing.

Most helpful comment

Hey @morpheus7CS, so this message is saying that the created_at, updated_at or deleted_at fields are returning a Illuminate\Support\Carbon instance rather than a string. There are 3 ways to handle this (directives, scalars, field resolver) but the easiest would be to create a custom directive like so:

// app/Http/GraphQL/Directives/DateTimeDirective.php

namespace App\Http\GraphQL\Directives;

use Carbon\Carbon;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\FieldResolver;
use Nuwave\Lighthouse\Support\Traits\HandlesDirectives;

class DateTimeDirective implements FieldResolver
{
    use HandlesDirectives;

    /**
     * Name of the directive.
     *
     * @return string
     */
    public function name()
    {
        return 'dateTime';
    }

    /**
     * Resolve the field directive.
     *
     * @param FieldValue $value
     *
     * @return FieldValue
     */
    public function resolveField(FieldValue $value)
    {
        $field = $value->getFieldName();

        return $value->setResolver(function ($root) use ($field) {
            $carbon = data_get($root, $field);

            // Format this however you want, but make sure it's a string
            return $carbon instanceof Carbon ? $carbon->toIso8601String() : $carbon;
        });
    }
}

And use it in your schema:

type Project {
    id: ID!
    parent_id: Parent @belongsTo
    name: String!
    created_at: String @dateTime
    updated_at: String @dateTime
    deleted_at: String @dateTime
}

Just a side note, I'll be creating a Carbon scalar and a @carbon(format: "YYYY-mm-dd") directive that will come with Lighthouse for you to use soon.

All 6 comments

I think your problem is created_at, etc... because those fields are Carbon instances.

I always create a Scalar Date to convert the carbon instace to a String representation.

Hey @morpheus7CS, so this message is saying that the created_at, updated_at or deleted_at fields are returning a Illuminate\Support\Carbon instance rather than a string. There are 3 ways to handle this (directives, scalars, field resolver) but the easiest would be to create a custom directive like so:

// app/Http/GraphQL/Directives/DateTimeDirective.php

namespace App\Http\GraphQL\Directives;

use Carbon\Carbon;
use Nuwave\Lighthouse\Schema\Values\FieldValue;
use Nuwave\Lighthouse\Support\Contracts\FieldResolver;
use Nuwave\Lighthouse\Support\Traits\HandlesDirectives;

class DateTimeDirective implements FieldResolver
{
    use HandlesDirectives;

    /**
     * Name of the directive.
     *
     * @return string
     */
    public function name()
    {
        return 'dateTime';
    }

    /**
     * Resolve the field directive.
     *
     * @param FieldValue $value
     *
     * @return FieldValue
     */
    public function resolveField(FieldValue $value)
    {
        $field = $value->getFieldName();

        return $value->setResolver(function ($root) use ($field) {
            $carbon = data_get($root, $field);

            // Format this however you want, but make sure it's a string
            return $carbon instanceof Carbon ? $carbon->toIso8601String() : $carbon;
        });
    }
}

And use it in your schema:

type Project {
    id: ID!
    parent_id: Parent @belongsTo
    name: String!
    created_at: String @dateTime
    updated_at: String @dateTime
    deleted_at: String @dateTime
}

Just a side note, I'll be creating a Carbon scalar and a @carbon(format: "YYYY-mm-dd") directive that will come with Lighthouse for you to use soon.

This is my solution,

<?php

namespace App\GraphQL\Scalars;


use Nuwave\Lighthouse\Schema\Types\Scalars\DateTime as LightDateTime;


class DateTime extends LightDateTime
{

}

and for your definitions:

type User @model {
  created_at: DateTime
  updated_at: DateTime
}

Thanks @kikoseijo!! When I push the update with the scalar and directive I'll check a config option for non-null that way it won't introduce any breaking changes for anyone who's using that scalar.

Ooops!
I meant to point it as an example, its a file with no use otherwise,

I guess best resolution for scalars and directives its to use users defined directories first for overwrite purposes, then, try to locate in lighthouse defined folders, I think this way saves us time to have it copy pasted.
Most people won't look for things to use inside libraries.

BTW if you want to get rid of those and let people have them written... happy with that also.

@chrissm79

I like the idea. The native @carbon directive would be very useful. Will it be considered on next version?

"Just a side note, I'll be creating a Carbon scalar and a @carbon(format: "YYYY-mm-dd") directive that will come with Lighthouse for you to use soon."

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexwhb picture alexwhb  路  4Comments

spawnia picture spawnia  路  3Comments

spawnia picture spawnia  路  4Comments

m1guelpf picture m1guelpf  路  3Comments

caizhigang97 picture caizhigang97  路  3Comments