youshido-php / graphql Goto Github PK
View Code? Open in Web Editor NEWPure PHP realization of GraphQL protocol
License: MIT License
Pure PHP realization of GraphQL protocol
License: MIT License
Hi. I have this code in the userEdit
field:
/**
* @inheritdoc
*/
public function getName()
{
return 'userEdit';
}
/**
* @inheritdoc
*/
public function getType()
{
return new UserType();
}
/**
* @inheritdoc
*/
public function build(FieldConfig $config)
{
$this->addArgument(
new InputField([
'name' => 'id',
'type' => new NonNullType(new IntType()),
])
)->addArgument(
new InputField([
'name' => 'data',
'type' => new NonNullType(new InputObjectType([
'name' => 'data',
'fields' => [
[
'name' => 'fullName',
'type' => new NonNullType(new StringType()),
],
],
])),
])
);
parent::build($config);
}
and the command:
mutation m {
userEdit(id: 1000000, data: 0) {
fullName
}
}
returns:
{
"errors": {
"message": "Type error: Argument 1 passed to Youshido\\GraphQL\\Validator\\ResolveValidator\\ResolveValidator::processInputObject() must be an instance of Youshido\\GraphQL\\Parser\\Ast\\ArgumentValue\\InputObject, instance of Youshido\\GraphQL\\Parser\\Ast\\ArgumentValue\\Literal given, called in /var/www/symfony/vendor/youshido/graphql/src/Validator/ResolveValidator/ResolveValidator.php on line 101"
}
}
Any unexpected value ([]
, 0
, "str"
) for the data
argument is not validated and causes to TypeError
.
Also this request for the same schema:
mutation m {
userEdit(id: 1000000, data: {unknownField: "a"}) {
fullName
}
}
returns only []
without any errors/exceptions.
Hi @viniychuk,
Maybe, I am doing something wrong, but when I try define mutations in such a way:
private function getRootMutation() {
return new ObjectType([
'name' => 'RootMutation',
'fields' => [
// here's our likePost mutation
'likePost' => new LikePost()
]
]);
}
and then define LikePost in the following way:
class LikePost extends AbstractField
{
public function build(FieldConfig $config) {
$config->addArgument('id', new NonNullType(new IntType()));
}
public function getType()
{
return new IntType();
}
public function resolve($value, array $args, ResolveInfo $info)
{
return 2;
}
}
then it does not work. I receive error that likePost
field is undefined.
I tried also extending AbstractInputField
, however InputFieldConfig
does not contain addArgument
function.
Is it possible to do in the current version?
Here's my example which the runtime throws the exception:
Call to undefined method Youshido\GraphQL\Type\Object\ObjectType::resolve()
$productType = new ObjectType([
'name' => 'ProductType',
'fields' => [
'sId' => new IntType(),
'title' => new StringType(),
'comments' => new StringType(),
'price' => new FloatType(),
'priceStr' => new StringType(),
'finalPrice' => new FloatType(),
'finalPriceStr' => new StringType(),
'currency' => new StringType(),
'Link' => new StringType(),
'link' => new StringType(),
],
'resolve' => function() <------- is this allowed?
{
return [
'sId' => 100,
'title' => 'Starwar film',
'comments' => 'no comment',
'price' => 13.5,
'priceStr' => '$13.5',
'finalPrice' => 10.5,
'finalPriceStr' => '$10.5',
'currency' => 'USD',
'Link' => 'http://google.com',
'link' => 'http://google.com'
];
}
]);
I was following the first example in this section of readMe:
https://github.com/Youshido/GraphQL#objects
Hi
class PostType extends \Youshido\GraphQL\Type\Object\AbstractObjectType
{
/**
* @param \Youshido\GraphQL\Config\Object\ObjectTypeConfig|TypeConfigInterface $config
* @return mixed
*/
public function build($config)
{
$config->addField('id', [
'type' => new IdType(),
'resolve' => function ($value, $args){
return $value['post_id'];
},
]);
in my db, the id field is named post_id
, i want to resolve post_id
to id
but in resolve function, $value is always null
it seems you have issue in https://github.com/Youshido/GraphQL/blob/master/src/Execution/Processor.php#L274
because
if (!$resolved && $field->getType()->getNamedType()->getKind() == TypeMap::KIND_SCALAR) {
$resolved = true;
}
if ($resolveFunction = $field->getConfig()->getResolveFunction()) {
.....
} else {
$resolverValue = $resolveFunction($resolved ? $resolverValue : $contextValue, $fieldAst->getKeyValueArguments(), $resolveInfo);
}
}
when $resolved = true and $resolverValue = null, $resolveFunction will have null $contextValue
What is the difference between this project and https://github.com/webonyx/graphql-php ?
Both seem to provide a GraphQL server implementation in PHP.
Full query:
query {
user {
...fUser
reservations {
...fReservation
}
}
}
fragment fReservation on Reservation {
id
... on CourtReservation {
players {
id
user {
...fUser
}
}
}
... on ClassReservation {
user {
...fUser
}
}
}
fragment fUser on User {
id
fullname
}
When I debug ResolveValidator::assertValidFragmentForField()
, $fragment->getModel()
seems to be "User"
.
Where does User come from..? The fragment is only applied to reservations
, which is a new ListType(new ReservationInterface())
. Is it confused by fUser
?
When I try another server library, the query works. Which is wrong? The query seems correct...
Hi,
I have a Yii project that i have implemented with Youshido/GraphQL and it works great!
Based on Yiis classes i can autogenerate code for querys and now im looking on mutation.
Smal repo: https://github.com/Vendium/Youshido-GraphQL-Yii
In your documentation you have written that "You can create a mutation by extending AbstractObjectType", my question is how to do this so you dont get a big Schema file. For query its made easy by working with types that have relations with each other.
So dose any one have a small code exampel of how to work with mutations without geting a big schema file and what i assume is to place mutations in type files.
thanks!
Query:
mutation { // or query or empty
__typename
}
Response:
{
"errors": [
{
"message": "Field \"__typename\" not found in type \"Mutation\"",
"locations": [
{
"line": 20,
"column": 3
}
]
}
]
}
BTW: Big thanks for locations key ๐
Can we get an inline example of how to structure something for this:
{
Post(id: 1) {
title,
User {
name
}
}
}
It seems like a mistake use PHP empty() in IdType::isValidValue() method. May be it must be the same as StringType::isValidValue()? Or simple is_scalar() if null is not valid value for ID?
I was testing this library last week and noticed that you do not support the error locations that are part of the GraphQL spec.
Is there a way to enable this or is this in the works?
if fragment does not exist, PHP Fatal error: Call to a member function getModel() on null
.
query {
posts {
...post
}
}
I believe throwing of exception with something like Unknown fragment "post".
will be more usefull
Is there a recommended way only to resolve the fields that the consumer has requested? In our model we have a few run-time calculated fields, ideally these aren't resolved on every request if the consumer does not actually ask for them.
Poking around the code I can't see a way to find the actual fields requested in the field resolver. I can see the entire query but as a field can be exposed from multiple nodes in the graph it's hard to infer the context it is being resolved for.
Thanks
As the title says, if you define a field inside an inputobject that is in a list to be NonNullable, the validator does not catch it if the variable is not set.
I've attached my test-classes: TestMutation.zip.
The query I tried to run:
mutation{
Test(test:{
a:[
],
b:[
{
c:"aaaa"
},
{
}
],
}) {
name
}
}
The rules for TestInput:
$config -> addField('a' , ['type' => new ListType(new IntType()) , 'description' => 'a'])
-> addField('b' , ['type' => new ListType(new InputObjectType([
'name' => 'test_b',
'fields' => [
'c' => new NonNullType(new StringType()),
]
]))
])
-> addField('d' , ['type' => new InputObjectType([
'name' => 'test_d',
'fields' => [
'c' => new NonNullType(new StringType()),
]
])
])
The validator does catch it if the field c of d is not set.
Hi!
Thanks for the hard work you have put into this project!
I have a mutation field:
class CreatePartField extends AbstractField
{
public function getType()
{
return new PartInputType();
}
public function build(FieldConfig $config)
{
$config->addArguments(new PartInputType());
}
public function resolve($value, array $args, ResolveInfo $info)
{
// return something...
}
}
And the type:
class PartInputType extends AbstractInputObjectType
{
public function build($config)
{
$config
->addField('id', new IntType())
->addField('name', new NonNullType(new StringType()))
->addField('description', new NonNullType(new StringType()))
->addField('notes', new StringType())
->addField('minimumStock', new IntType());
}
}
I've add the field to the mutation fields:
class GraphQLSchema extends AbstractSchema
{
public function build(SchemaConfig $config)
{
$config->getQuery()->addFields([
new RetrievePartField(),
new AllPartsField(),
]);
$config->getMutation()->addFields([
new CreatePartField()
]);
}
}
I send the mutation request:
mutation { createPart( id: 3, name: "Another test", description: "Another description", minimumStock: "12", notes: "Another note") }
I keep getting the error: Unknown argument "id" on field "createPart"
The field doesn't seem to like accepting AbstractInputObjectType
as an argument (maybe?)
I've looked into all of the docs and examples, but I have not yet found a solution...
Perhaps I'm formatting the mutation request wrong...
Any help would be greatly appreciated! Thank you!
ArrayConnection::connectionFromArraySlice is not slicing corretly when using "after" or "before" as parametersin the query
@svrcekmichal idea:
We need a way to pass some custom data in context? For example auth user, something like in https://github.com/graphql/express-graphql at the bottom of docs.
GraphQL Fields can have arguments. It is easy to do in inline-approach, however, I cannot achieve it in object oriented approach. I need it badly. I edited this function in the following way:
public function getRules()
{
return [
'name' => ['type' => TypeService::TYPE_STRING, 'required' => true],
'description' => ['type' => TypeService::TYPE_STRING],
'fields' => ['type' => TypeService::TYPE_ARRAY_OF_FIELDS_CONFIG, 'final' => true],
'interfaces' => ['type' => TypeService::TYPE_ARRAY_OF_INTERFACES],
'args' => ['type' => TypeService::TYPE_ARRAY_OF_INPUT_FIELDS]
];
}
However, still $args
are empty in the resolve
function. Do you know how to do that easily? I will be grateful for any help.
I have a mutation, defined as such:
<?php
namespace AppBundle\GraphQL\Mutation;
use AppBundle\GraphQL\Type\TestMutationInputType;
use Youshido\GraphQL\Config\Field\FieldConfig;
use Youshido\GraphQL\Execution\ResolveInfo;
use Youshido\GraphQL\Type\NonNullType;
use Youshido\GraphQL\Type\Scalar\IntType;
use Youshido\GraphQLBundle\Field\AbstractContainerAwareField;
class TestMutationField extends AbstractContainerAwareField
{
/**
* {@inheritdoc}
*/
public function getType()
{
return new IntType();
}
/**
* {@inheritdoc}
*/
public function build(FieldConfig $config)
{
$config->addArgument('input', new NonNullType(new TestMutationInputType()));
}
/**
* {@inheritdoc}
*/
public function resolve($value, array $args, ResolveInfo $info)
{
return 0;
}
}
The input type is defined as such:
<?php
namespace AppBundle\GraphQL\Input;
use Youshido\GraphQL\Type\InputObject\AbstractInputObjectType;
use Youshido\GraphQL\Type\ListType\ListType;
use Youshido\GraphQL\Type\NonNullType;
use Youshido\GraphQL\Type\Scalar\StringType;
class TestMutationInputType extends AbstractInputObjectType
{
/**
* {@inheritdoc}
*/
public function build($config)
{
$config->addFields([
'nullField' => new StringType(),
'nonNullField' => new NonNullType(new StringType()),
]);
}
}
Executing this mutation and providing values for all the fields on the input type fails with the following message:
{
"data": {
"testMutation": null
},
"errors": [
{
"message": "Not valid type for argument \"input\" in query \"testMutation\""
}
]
}
If I then remove the NonNullType from nonNullField
the mutation executes correctly. I've poked through the code but nothing obvious stood out to me.
Regards
I think the name Field used for GraphQL(Youshido) is different from Field in GraphQL documentation.
Field in GraphQL(Youshido) refers to an instance of a type(object) (including the resolve method).
Field in GraphQL(doc) refers to property of a object.
If my understanding is correct. Shall we use another name for Field for Youshido?
tried on last version
schema:
type Query {
user: User
}
type User {
key: Int
}
query:
{
user {
key { // empty selection, causing invalid query
}
}
}
If i user graphql-js
:
{
"errors": [
{
"message": "Syntax Error GraphQL request (5:5) Expected Name, found }\n\n4: \n5: }\n ^\n6: }\n",
"locations": [
{
"line": 5,
"column": 5
}
]
}
]
}
With this package:
{
"data": {
"user": {
"key": null
}
}
}
There is no error thrown and also invalid data, key data should be available only if execution of query started, not in part of validating schema
{
oneComparison: Post(id: 1) {
title
}
twoComparison: Post(id: 1) {
...Fields
}
}
fragment Fields on Post {
title
}
Returns this:
{"data":{"oneComparison":{"title":"string"},"twoComparison":[]}}
In the examples ListType is used with interfaces
But what if I want a list of posts? How do you handle that?
Tried as ListType ( new PostType()) and returned an array of posts and it didn't work.
Thanks!
PS: Thanks for the awesome work ! tried many tools and this one was the best php helper/library I found, very well documented. I just made a PR to the awesome list for PHP related projects:
chentsulin/awesome-graphql#71 #71
If you request a subfield which is not defined, you get a fatal error.
{Test{
name,
bla {
}
}}
The test-type only has the field name defined. The subfield bla is never defined which causes the fatal error.
( ! ) Fatal error: Uncaught TypeError: Argument 2 passed to Youshido\GraphQL\Execution\Processor::processQueryAST() must be an instance of Youshido\GraphQL\Field\AbstractField, null given, called in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 332 and defined in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 127 | ||||
---|---|---|---|---|
( ! ) TypeError: Argument 2 passed to Youshido\GraphQL\Execution\Processor::processQueryAST() must be an instance of Youshido\GraphQL\Field\AbstractField, null given, called in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 332 in /home/pieter/workfiles/sigura-industries/vendor/youshido/graphql/src/Execution/Processor.php on line 127 | ||||
Call Stack | ||||
# | Time | Memory | Function | Location |
1 | 0.0002 | 384928 | {main}( ) | .../graphql.php:0 |
2 | 0.0089 | 706880 | Sigura\Mods\Industries\Graphql->__construct( ) | .../graphql.php:8 |
3 | 0.1232 | 2184024 | Youshido\GraphQL\Execution\Processor->processPayload( ) | .../Graphql.class.php:122 |
4 | 0.1248 | 2253088 | Youshido\GraphQL\Execution\Processor->executeOperation( ) | .../Processor.php:76 |
5 | 0.1249 | 2270560 | Youshido\GraphQL\Execution\Processor->processQueryAST( ) | .../Processor.php:118 |
6 | 0.1251 | 2395400 | Youshido\GraphQL\Execution\Processor->collectValueForQueryWithType( ) | .../Processor.php:135 |
7 | 0.1252 | 2398864 | Youshido\GraphQL\Execution\Processor->processQueryFields( ) | .../Processor.php:171 |
8 | 0.1254 | 2424840 | Youshido\GraphQL\Execution\Processor->processQueryAST( ) | .../Processor.php:332 |
Hi,
i've created a middleware based on your implementation of GraphQL spec.
https://github.com/stefanorg/graphql-middleware
I've also created a demo app, like you did for symphony, using zend-expressive: https://github.com/stefanorg/graphql-expressive-demo
Feel free to give some feedback!
Thanks for the work done with the library.
schema:
type Query {
getSomething(sort:SortType): String //sort not required
}
query:
query SomeQuery($sort:SortType) {
getSomething(sort: $sort)
}
variables:
NONE or
{}
response
{
"errors": [
{
"message": "Variable \"sort\" does not exist for query \"getSomething\""
}
]
}
tried on last version
schema:
type Query {
user: User
}
type User {
key: Int
}
query:
{
user {
key {
someKey // trying to sub-select on Int
}
}
}
If i user graphql-js
:
{
"errors": [
{
"message": "Field \"key\" of type \"Int\" must not have a sub selection.",
"locations": [
{
"line": 3,
"column": 9
}
]
}
]
}
With this package:
{
"data": {
"user": {
"key": null
}
}
}
There is no error thrown and also invalid data, key data should be available only if execution of query started, not in part of validating schema
I'm using NonNullType
in my return type like this:
class PersonType extends AbstractObjectType
{
/**
* @param ObjectTypeConfig $config
*
* @return mixed
*/
public function build($config)
{
$config->addFields([
'id' => new NonNullType(new IdType()),
'firstName' => new NonNullType(new StringType()),
'lastName' => new NonNullType(new StringType()),
]);
}
}
The IDs of my persons are UUIDs. With the code like this, the result is:
{
"data": {
"persons": [
{
"id": {},
"firstName": "Bernhard",
"lastName": "Schussek"
}
]
}
}
As you can see, the UUID is not cast to a string, but converted to {}
. However if I remove the NonNullType
around IdType
, the result is as expected:
{
"data": {
"persons": [
{
"id": "6cfb044c-9c0a-4ddd-9ef8-a0b940818db3",
"firstName": "Bernhard",
"lastName": "Schussek"
}
]
}
}
if I fire query
query queryWithVariable($abc:String) {
userById(id: 2) {
...someFragment
}
}
without someFragment
I get error Not all variables in query was used
, I believe it would be better to tell user he has missing fragment in query, because fragment could used that variable.
Object wrapped in NonNullType returns __type null
instead of valid typename
Thank you for good documentation, however. there is a problem with description of inline-approach:
<?php
use Youshido\GraphQL\Type\Object\ObjectType;
use Youshido\GraphQL\Type\Scalar\StringType;
// creating a root query structure
$rootQueryType = new ObjectType([
// name for the root query type doesn't matter, by the convention it's RootQueryType
'name' => 'RootQueryType',
'fields' => [
'latestPost' => new ObjectType([ // the Post type will be extended from the generic ObjectType
'name' => 'Post', // name of our type โ "Post"
'fields' => [
'title' => new StringType(), // defining the "title" field, type - String
'summary' => new StringType(), // defining the "summary" field, also a String type
],
'resolve' => function () { // this is a resolve function
return [ // for now it returns a static array with data
"title" => "New approach in API has been revealed",
"summary" => "This post describes a new approach to create and maintain APIs",
];
}
])
]
]);
Resolve function cannot be there. It is not valid.
This query combining unions and fragments does not work:
{
user(id: 2) {
...user
}
}
fragment user on UserUnion {
... on User {
id
}
}
schema contains query user
which can return UserUnion
which will be resolved to type User
with field id
. Exception thrown: Fragment reference "user" not found on model "User"
If !Int
is resolved to null
, there's no error or exception thrown
$config->addField('id', [
'type' => new NonNullType(new IntType()),
'resolve' => function() { return null; }
]);
graphql-js
is notificating about this behavior with
{
"message": "Cannot return null for non-nullable field User.id.",
"locations": [
{
"line": 5,
"column": 5
}
]
}
in response errors
key. Same is returned if resolver returns string not coercible to int.
This works fine:
{ foo { bar(value:"baz") } }
But the following equivalent query with provided variables {value:"baz"}
bombs out:
query nestedQuery($value:String!){
foo {
bar(value:$value)
}
Error message is somewhat opaque: "Value not set to variable else"
I've provided a regression test here: roippi@54f310b
The fix is non-trivial so I don't know if/when I'll have a pull request available. I've traced through it and it looks like $this->resolveValidator->validateArguments
is only getting invoked at the operation level, not at the individual field level.
Thanks for the awesome library.
This is a feature that's popping up in a few other framework implementations, and I think it's pretty killer - it lets you do a reasonable job at statically detecting pathologic queries.
There are some more complex ideas floating out there in the community, namely graphql/graphql-js#304. This could be used both for complexity/cost analysis in addition to query resolution optimization, though it seems more useful for optimization. Probably overkill here.
Has anyone already thought of implementing this here, or should I take a crack at it?
Lets say I have a mutation like this
mutation
{createPost(
title: 'Copa America',
description: ' Latest results ',
authors: [
{name: 'Maradona', email: '[email protected]' } ,
{name: 'Messi', email: '[email protected]' } ]
)}
How Do I handle this scenario? -
I tried the author ListType( new AuthorType()) ?
ListType is not iterating each AuthorType sent on the request so its failing with Not valid Type....
ResolveValidator line
if (!$argumentType->isValidValue($argumentType->parseValue($argument->getValue()->getValue()))) {
Is receiving the entire array sent and not a single iteration..
I guess we need a InputListType ? or I am missing something
@fubhy's comments in gitter:
Fragments currently don't work with interfaces or union types... only normal types or composite types.
E.g. this doesn't work:
query {
somethingThatReturnsAUnion(foo: "bar") {
... on Something { // Something is a valid type for this union!
id
}
}
}
That is, because we currently only load the inner type (resolve any compose types) and then compare the name of that type with the name of the fragment. In case of unions/interfaces however, we need to also compare it with any of the possible types of the interface/union.
And even possible further nested types.
Will add failing test case.
Is there a possibility of extending types?
For example, if I have PostType and I want to create the next type called SpecialPostType (which has all fields that PostType has, but also a few additional), can I extend it somehow?
I do not want to use Interfaces, because as far as I understand, Interfaces will make me to define resolve functions for PostType and SpecialPostType separately.
This issue is a request for having the Requested fields inside the resolve function.
The idea is not to retrieve unnecessary data.
This has been tackled on graphql/graphql-js#19 - maybe you could get an idea.
thanks
Hi,
Using a "-" in the name of an enum causes this error:
{
"errors": [
{
"message": "Config is not valid for TestType\nField \"values\" expected to be \"type\" but got \"array\""
}
]
}
Code:
use \Youshido\GraphQL\Type\Object\AbstractObjectType;
use \Youshido\GraphQL\Type\Scalar\IdType;
use \Youshido\GraphQL\Type\Scalar\StringType;
use \Youshido\GraphQL\Type\Scalar\DateType;
use \Youshido\GraphQL\Type\Scalar\BooleanType;
use \Youshido\GraphQL\Type\ListType\ListType;
use \Youshido\GraphQL\Type\Enum\AbstractEnumType;
class TestType extends AbstractEnumType
{
public function getValues()
{
$result = array();
$result[]= array(
'value' => 1,
'name' => "aaa-",
);
$result[]= array(
'value' => 2,
'name' => "bbb",
);
return $result;
}
}
Query like this:
{
user(id: 11457349) {
}
}
is invalid, but it is possible to execute it with package. It will resolve to all user
keys, but I don't believe this is valid either. Can you confirm this? Or am I mistaken?
Query:
query userById($offset:Int) {
user(id: 2) {
id
photoAlbums(offset: $offset) {
edges {
id
}
}
}
}
Response:
{
"data": {
"user": {
"id": 2,
"photoAlbums": null
}
},
"errors": [
{
"message": "Variable \"offset\" does not exist for query \"photoAlbums\""
}
]
}
If i dont use named query
{
user(id: 2) {
id
photoAlbums {
edges {
id
}
}
}
}
response is
{
"data": {
"user": {
"id": 2,
"photoAlbums": {
"edges": [
{
"id": 10000965
},
....
]
}
}
}
}
Based on this release: https://github.com/facebook/graphql/releases/tag/October2016
The library should support null
value.
As an example see issue #89 where DateTimeType throw error both for "unserialize" and "serialize" null value as parameter.
If you can give feedback i can provide a PR for this maybe.
Hi,
First up - awesome work, I just started looking into this project after working with GraphQL-php for some time. I really like the OOP type declaration approach.
I come across an issue in the getting started document, which I think might just be outdated documentation?
public function build(TypeConfigInterface $config)
{
$config
->addField('title', new NonNullType(new StringType()), [
'description' => 'This field contains a post title',
'isDeprecated' => true,
'deprecationReason' => 'field title is now deprecated',
'args' => [
'truncated' => new BooleanType()
],
'resolve' => function ($value, $args) {
return (!empty($args['truncated'])) ? explode(' ', $value)[0] . '...' : $value;
}
])
->addField('summary', new StringType())
->addField('likeCount', new IntType());
$config->addArgument('id', new IntType());
}
public function resolve($value, $args, $info)
{
return [
"title" => "Title for the latest Post",
"summary" => "Post summary",
"likeCount" => 2
];
}
inline documentation says it is ObjectTypeConfig and not TypeConfigInterface.
addFields only takes 2 arguments, how is it configured then?
AbstractObjectType does'nt not contain a resolve() to override, and if I define a resolve function here, it is not called.
Hi,
using DateTimeType enforce string validation against a date format, i found that the actual implementation of DateTimeType doesn't allow null
value as mutation parameter and as scalar value.
As an example if in the todo
example app we add a expire
field as DateTime we can query
class TodoType extends AbstractObjectType
{
public function build($config)
{
$config->addFields([
'id' => new NonNullType(new IdType()),
'title' => new StringType(),
'completed' => new BooleanType(),
'expire' => new DateTimeType("d-m-Y")
]);
}
}
if we issue a query
fragment todo on Todo {
id
title
completed
expire
}
{
todos {
...todo
}
}
we get
{
"data": {
"todos": [
null
]
},
"errors": [
{
"message": "Not valid resolved type for field \"expire\""
}
]
}
Also in case of mutation
mutation {
save(id:1, title: "todo mod", expire: null) {
...todo
}
}
the error is
{
"data": {
"save": null,
"toggleAll": [
null
]
},
"errors": [
{
"message": "Not valid type for argument \"expire\" in query \"save\"",
"locations": [
{
"line": 10,
"column": 34
}
]
},
{
"message": "Not valid resolved type for field \"expire\""
}
]
}
tried on last version
schema:
type Query {
user: User
}
type User {
key: Int!
}
query:
{
user {
key
}
}
If i user graphql-js
:
{
"data": {
"user": null
},
"errors": [
{
"message": "Cannot return null for non-nullable field User.key.",
"locations": [
{
"line": 3,
"column": 5
}
]
}
]
}
With this package:
{
"data": {
"user": {
"key": null
}
}
}
There is no error thrown
Currently when using a custom resolver on a field, the returned value gets overwritten if the parent value is an object or an array.
See #40 (comment)
Hi, we've run in to a situation where if we execute a query such as:
{
name
primaryAddress
}
Where primaryAddress
is a complex object with it's own type. We receive a response like so:
{
"name": "Bob",
"primaryAddress": {
},
"__cloner__": {
},
"__isInitialized__": false
}
}
The types are configured like so:
<?php
namespace App\AppBundle\GraphQL;
use Youshido\GraphQL\Type\ListType\ListType;
use Youshido\GraphQL\Type\Object\AbstractObjectType;
use Youshido\GraphQL\Type\Scalar\BooleanType;
use Youshido\GraphQL\Type\Scalar\DateTimeTzType;
use Youshido\GraphQL\Type\Scalar\DateType;
use Youshido\GraphQL\Type\Scalar\FloatType;
use Youshido\GraphQL\Type\Scalar\IdType;
use Youshido\GraphQL\Type\Scalar\IntType;
use Youshido\GraphQL\Type\Scalar\StringType;
class PersonType extends AbstractObjectType {
/**
* @param mixed $config
*/
public function build($config) {
return $config
->addFields(['name' => ['type' => new StringType(), 'description' => 'The name of the person']])
->addFields(['primaryAddress' => ['type' => new AddressType(), 'description' => 'Their primary address']])
}
/**
*/
public function getName() {
return "Person";
}
}
class AddressType extends AbstractObjectType {
/**
* @param mixed $config
*/
public function build($config) {
return $config
->addFields(['street' => ['type' => new StringType(), 'description' => 'The street']])
->addFields(['postcode' => ['type' => new StringType(), 'description' => 'The postcode']]);
}
/**
*/
public function getName() {
return 'Address';
}
}
We are using doctrine behind the scenes, this seems to be outputting the contents of our proxy object. If we execute the query with an empty field list (e.g. primaryAddress {}) then the query fails with an expected message of "You have to specify fields for primaryAddress". I would expect the same result if you miss off the braces.
Are we misconfiguring our types or is this a bug?
Regards,
$config->addField('date', new TimestampType());
In my database, i have field date
as unix timestamp (which is integer)
In this class
https://github.com/Youshido/GraphQL/blob/master/src/Type/Scalar/TimestampType.php
public function isValidValue($value)
{
if (is_object($value)) {
return true;
}
return is_int($value);
}
if i pass an integer, it will return true
but when it is being serialized
public function serialize($value)
{
if ($value === null || !is_object($value)) {
return null;
}
return $value->getTimestamp();
}
the previous valid integer will be serialized into null
Hi
Query:
mutation {
upvote(idPhotos:[320131273]) {
id
}
}
If i define idPhotos
this way
$config->addArgument('idPhotos', new NonNullType(new ListType(new IntType())));
I get error Not valid type for argument "idPhotos" in query "upvote"
, but if I define it this way
$config->addArgument('idPhotos', new NonNullType(new ListType(new NonNullType(new IntType()))));
everything works as expected.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.