Giter Site home page Giter Site logo

webonyx / graphql-php Goto Github PK

View Code? Open in Web Editor NEW
4.6K 113.0 563.0 7.77 MB

PHP implementation of the GraphQL specification based on the reference implementation in JavaScript

Home Page: https://webonyx.github.io/graphql-php

License: MIT License

PHP 99.96% Makefile 0.04%
php graphql api api-management graphql-php rest-replacement

graphql-php's Introduction

graphql-php

CI Coverage Status Latest Stable Version

This is a PHP implementation of the GraphQL specification based on the reference implementation in JavaScript.

Installation

Via composer:

composer require webonyx/graphql-php

Documentation

Full documentation is available at https://webonyx.github.io/graphql-php or in the docs directory.

Examples

There are several ready examples in the examples directory, with a specific README file per example.

Versioning

This project follows Semantic Versioning 2.0.0.

Elements that belong to the public API of this package are marked with the @api PHPDoc tag. Those elements are thus guaranteed to be stable within major versions. All other elements are not part of this backwards compatibility guarantee and may change between minor or patch versions.

The most recent version is actively developed on master. Older versions are generally no longer supported, although exceptions may be made for sponsors.

Security

For security related issues, email [email protected] instead of opening a GitHub issue.

Contributors

This project exists thanks to all the people who contribute.

Backers

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. Become a sponsor.

License

See LICENSE.

graphql-php's People

Contributors

andheiberg avatar chrisdowson avatar chriszarate avatar danez avatar decebal avatar dmongeau avatar enumag avatar gabidj avatar janbukva avatar kingdutch avatar lastdragon-ru avatar mcg-web avatar mfn avatar n1ru4l avatar nagledb avatar powerkiki avatar renovate-bot avatar renovate[bot] avatar roippi avatar ruudk avatar shmax avatar simpod avatar spawnia avatar stayallive avatar torsten85 avatar urbanc avatar vhenzl avatar vladar avatar warxcell avatar yura3d avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-php's Issues

Example for mutation

That would be great if we also have an example on file uploading example.

Thanks!

Field definition for InterfaceType does not work with callback function

This is possibly related to #22. When I try to define the fields as a callback function for an InterfaceType, I get an error:

Argument 1 passed to GraphQL\Type\Definition\FieldDefinition::createMap() must be of the type array, object given, called in /Users/ivo/Documents/workspace/graphql-relay-php/vendor/webonyx/graphql-php/src/Type/Definition/InterfaceType.php on line 66 and defined

Consider adding chainable syntax to Schema or SchemaBuilder

Example of how schema initialization might look like (see #36 for discussion on this subject):

$schema = new GraphQL\Schema();
$schema->setQueryType( $objectType)
    ->setMutationType($mutationType)
/* Other possible setters:
   ->setDirectives($directives)
   ->setTypes($types)
*/

One liner shorthand for field definition?

Currently for field (such as currency in below example), only array type definition is allowed (has to be an array within which defines a "type"). In other GraphQL implementations such as https://github.com/Youshido/GraphQL, a simpler shorthand like this is allowed:

Proposed
'currency' => Type::string()

Current

      $ProductType = new ObjectType([
            'name' => 'Product',
            'fields' => [
                'title'         => [
                    'type' => Type::string()
                ],
                'priceStr'      => [
                    'type' => Type::string()
                ],
                'currency'      => [
                    'type' => Type::string()
                ]
            ]
        ]);

I have a rough code change that can convert to a pull request, if more ppl find it handy.

Modifying context inside a resolver does not propagate to child resolvers

Context is supposed to be something you can pass down to any resolver, and modify from any point, but I wasn't able to make this work without changing the line in https://github.com/webonyx/graphql-php/blob/master/src/Executor/Executor.php#L460 to

return $resolveFn($source, $args, $context, $info);

Without this change, defining the resolve function as function ($parent, $args, &$context, $ast) {} is an error because of some bug/weird behaviour with call_user_func

EDIT: I've made the change in my fork over at https://github.com/JohnyDays/graphql-php/tree/directlyCallResolver, should I open a pull request, or am I missing something? Cheers!

EDIT2: I actually had to change a few more lines in the end to make it work, assigning context by reference.

Load types in schema on demand

Currently all types (including all fields) are loaded on schema instance creation.

It is suboptimal for PHP, but it works this way because in some cases we need to know all interface implementors (for validation purposes - both in Validator and in Executor). And the only way to find them is to loop through all types and check if type implements given interface. Hence all types must be loaded for interface-related checks.

The goal of this task is to find a way for lazy-loading types in schema. This is possible, yet requires additional hints from user-land code to work efficiently (e.g. #40).

Implement findBreakingChanges utility

Reference implementation has nice findBreakingChanges utility which allows to compare two schemas to figure out if newer one contains breaking changes.

Add examples + readme

Without more information this project looks interesting but I'm not sure how to even get started. Is this something you're going to be expanding on in the future?

Deprecate passing query, mutation and subscription types to Schema constructor directly

After this change following code will trigger deprecation notice:

$schema = new GraphQL\Schema($objectType, $mutationType);

It should be rewritten with

$schema = new GraphQL\Schema([
    'query' => $objectType,
    'mutation' => $mutationType,
    // Other possible options:
    // 'directives' => $directives
    // 'subscription' => $subscription,
    // 'types' => $types
])

Type name is null in introspection when using Type::listOf

As described in the issue folkloreinc/laravel-graphql#50 the type name is null when using listOf.

Query:

{  
  __type(name: "User") { 
    name 
    fields { 
      name 
      type { 
        name 
      } 
    } 
  } 
}

Response:

{
  "data":{
    "__type":{
      "name": "User",
      "fields":[
        {"name": "followings", "type":{"name": null }},
      ]
    }
  }
}

I suspect this is because public $name is not set in the ListOfType. It may be setted in the constructor. I can submit a pull request if it makes sense.

Deprecate callbacks in field types

Deprecate following field definition form:

[
    'name' => 'Foo',
    'fields' => [
        'bar'  => ['type' => function()  use(&$barType) { return $barType;}],
        'baz'  => ['type' => function()  use(&$bazType) { return $bazType;}],
    ]
]

in favor of:

[
    'name' => 'Foo',
    'fields' => function() use (&$barType, &$bazType) {
        return [
            'bar' => ['type' => $barType],
            'baz' => ['type' => $bazType],
        ];
    }
]

Use of map() where parent type is a node

Resolving fields with map works really well (and fast!) when the parent type is a list. However, when using Relay connections, it's impossible to use map on the "connected" type, since its parent is an edge and not the list of edges.
An example:
UserType -> todos -> TodoConnection -> edges -> EdgeType -> node -> TodoType -> items*
I want to use map on items but I cant since the root argument will contain an array with only one element - the edge.

Is there any way to work around this, or is it perhaps something you would consider improving?

[Proposal] Resolve directly vs promise

When using GraphQL to a higher level you might need promise resolver to manage data loader by example. My proposal it to implement this missing feature. We can use one of those two lib to full fill that need:

amphp/amp look to be the right solution but required php >= 5.5...

what do you think of this?

A type can't be reused for multiple queries/mutations

When creating a root query & mutation with the same result type, an exception is thrown:

Schema must contain unique named types but contains multiple types named "<type>".

I would think it's rather common to reuse the same type โ€“ e.g. when returning an instance after creating it.
The express-graphql implementation allows this, I quickly checked.

When commenting out that check in \GraphQL\Schema everything seems to work, too.. Any particular reason for this invariant?

PS: Great library, very useful! ;)

Use & lazy load class names instead of full definition objects

It seems very inefficient to load the entire schema for every query every time. I have a very small schema (5 types, 1 interface) and it takes 10 ms just to define the schema. Would it be possible to hint to class names instead of objects. This would also 'fix' the many &$postType references (and closures), because the objects are really lazy loaded.

I've no idea if this would be possible. It might have huge downsides. It definitely takes a lot of change. You might've tried something like this already.

Just to clarify, this is what it would look like (in my naive mind):

$schema = new Schema([
    'query' => QueryType::class,
    'types' => [
        UserType::class,
        CourtReservationType::class,
        ClassReservationType::class,
        PlayerType::class,
    ],
]);

Schema or Executor or anyone could cache the objects by class name. All references would be class names:

'type' => Type::listOf(ReservationInterface::class),
'interfaces' => [ReservationInterface::class],

etc.

This would make the simple examples more complex, but reality simpler IMO. Every type would require a class, but not memory, until needed.

Like I said, no idea how feasible this is. Just a thought.

Keep up the good work

Well, this isn't really an issue, but more an encouragement to keep up the good work -- this project is going to be really helpful for PHP users.
Thanks (and +1 star)
๐Ÿ‘

Allow interface type definition to hint about interface implementors

Now when interface implementor is not referenced anywhere in schema it remains invisible for GraphQL during validation phase.

As a workaround we allow types option on Schema to pass such implementors directly. But a better way for this could be adding implementors option to interface type definition that could act as a hint for schema.

This option will accept an array or thunk of types (similar to fields and interfaces options on ObjectType).

This mechanism will have advantages over current types option on Schema only when type definitions are initialized on demand (vs collected during schema creation as it is done now).

See #38 for more info

Interface lazy loading, field definitions as closure not working

I am having some issues with the new lazy loading of interfaces that was implemented:

I have all of my fields defined in callback functions and inside of those callback functions I have a typeRegistry that creates the types on demand. That has the massive advantage that the instances of the types are only created when they are needed.
That worked fine until the latest version when lazy loading of interfaces was introduced. The loading of the interfaces seems to be called on schema creation:

https://github.com/webonyx/graphql-php/blob/master/src/Schema.php#L36

So the types with interfaces are not known at this point in my setup, because the callback functions that create the types did not execute yet.
When the interface is called, I'm getting an error, because the types are not recognized properly.

The following example query:

query Query {
  node(id: "UmVnaW9uOjRhYWNkZTQwNzBhZWIxY2RhZTAy") {
    ... on User {
      firstname
    }
    id
  }
}

Results in an error:

{
  "data": null,
  "errors": [
    {
      "message": "Fragment cannot be spread here as objects of type \"Node\" can never be of type \"User\".",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ]
    }
  ]
}

If I change the function getPossibleTypes to the following, it works again, at least the error is gone

    public function getPossibleTypes()
    {
        if (self::$_lazyLoadImplementations) {
            self::loadImplementationToInterfaces();
        }
        return $this->_implementations;
    }

The node is resolved properly but I don't get the fields returned from the fragments. That was also not working with the previous version v0.5.7.
So I'm wondering if there is something else wrong with the InterfaceType, possibly in combination with the definition of the fields in the callback functions. But I feel like creating them on demand would be the most performant way.
What do we need the lazy loading for, if the function loadImplementationToInterfaces is called in the Schema constructor?

Any ideas how I should fix that?

Using fragments

Its not clear how implement fragment in php code ??
Any example for that ??

Ability to defer field resolution (to solve N+1 problem)

There were several discussions about ways to solve N+1 problem in GraphQL - #42, #60.

There are two classes of solutions for this problem:

  1. Look-ahead soltion when we analyze the query and pre-fetch required data upfront (see #65)
  2. Defer field resolution (and thus enable batching queries using techniques like DataLoader)

Deferring syntax:

'resolve' => function($obj) {
    $this->dataLoader->buffer($obj->someId);

    return new GraphQL\Deferred(function() use ($obj) {
       // This will internally load all buffered ids (once) and return the one requested here:
        return $this->dataLoader->fetch($obj->someId);
    });
}

Other possible syntax:

'buffer' => function($obj) {
    $this->dataLoader->buffer($obj->someId);
},
'resolve' => function($obj) {
    return $this->dataLoader->fetch($obj->someId);
}

Technically it will require Executor algorith change from Depth-First to mix of Breath-First and Depth-First (requires researching and prototyping).

Error Handling

I have been looking around at the source code and haven't come across a way to do this yet, so I figured I would reach out. I am trying to make multiple requests such as this:

{
  users {
    id,
    name
  },
  posts {
    id,
    title
  }
}

Now what I want to do is cause an error on just one of those queries and allow the other to continue. So ideally it would be nice if we could find out where the error was that way we could key the errors array like this:

array(
  'errors' => array(
    'users' => array(
    )
  )
)

Is there something I am missing here or is this really not possible to see which query threw the error right now?

Mutations with Relay (React)

I'm using the laravel-graphql, and created an issue but I'm not sure if it's something that should actually be created here (still trying to wrap my head around GraphQL).

When working with Relay, it expects that mutations have only one argument called input. Looking at the todo example, in the schema.json file it has that field listed as an INPUT_OBJECT type. I created the following (again, using laravel-graphql), but I'm unable to get the fields from the InputObjectType. Am I doing something wrong?

namespace App\GraphQL\Mutations;

use GraphQL;
use App\Models\Customer;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\InputObjectType;
use Folklore\GraphQL\Support\Mutation;

class UpdateCustomerEmail extends Mutation
{
    /**
     * Associated GraphQL Type.
     *
     * @return mixed
     */
    public function type()
    {
        return GraphQL::type('customerPayload');
    }

    /**
     * Available arguments for mutation.
     *
     * @return array
     */
    public function args()
    {
        return [
            'input' => [
                'name' => 'input',
                'type' => new InputObjectType([
                    'name' => 'updateCustomerEmailInput',
                    'fields' => [
                        'entity_id' => [
                            'name' => 'entity_id',
                            'type' => Type::nonNull(Type::string())
                        ],
                        'email' => [
                            'name' => 'email',
                            'type' => Type::nonNull(Type::string())
                        ]
                    ]
                ])
            ]
        ];
    }

    /**
     * Resolve mutation.
     *
     * @param  string $root
     * @param  array $args
     * @return Customer
     */
    public function resolve($root, $args, $info)
    {
        // $root is null, $args is an empty array and nothing in $info gives me the 
        // variables passed in the request
        $customer = Customer::find($args['input']['entity_id']); // $args['input'] is not set
        $customer->email = $args['input']['email'];
        return $customer;
    }
}

defaultValue for argument of InputObjectType

Currently Introspection for __InputValue.defaultValue uses json_encode, which works for simple input values, but fails when input type is a complex InputObjectType.

Currently introspection produces following value:

[{"selectId":"value","selectedOptions":["a", "b", "c"]}]

While GraphQL JS (and Relay) expect:

[{selectId: "value", selectedOptions: ["a", "b", "c"]}]

Need to implement custom astFromValue helper and use Printer instead of json_encode.

Horizontal eval for lazy loading same-type objects

When I first learned about GraphQL there was a performance chapter. If every relation loads every single relation, it requires many queries to load a few levels of data, even if the actual data is only on the last level. The solution was to lazy load objects: first collect ids (horizontal), and then load all objects at once, and then evaluate the next level.

Just in case. This query:

query {
    user {
        reservations {
            resource {
                sport {
                    name
                }
            }
        }
    }
}

would take 20 queries to find 10 reservations > 10x 1 resource > 10x 1 sport. If it would eval horizontally, it would do 2 queries: load 10 resources, then load 10 sports. (Maybe not 2 levels, but even 1 could be a big difference.)

Is that a thing? It seems like the query is evaled vertically first, so it loads the entire 1 reservation (1 resource + 1 sport), and then the entire 1 next (1 resource + 1 sport) etc.

Empty object is [] instead of {}

query { user { reservations } } returns ReservationInterfaces, implemented by XReservation and YReservation. Let's say it returns 2 XReservations and 2 YReservations. If you add an inline fragment to only return anything for XReservations, the 2 YReservations will be completely empty. An empty array in PHP translates to an empty array in JSON, instead of an empty object.

Query:

{
    user {
        reservations {
            ... on XReservation {
                id
            }
        }
    }
}

Result:

reservations: [
  {id},
  {id},
  [],
  []
]

I think those 2 [] should be {}, because they're known objects, not lists.

Performance improvements

I've been messing around with this project a bit lately, and I've had some trouble with performance. The GraphQL executor does quite a bit of unnecessary work when it resolves fields. Since it operates recursively, larger lists have a really bad impact on performance. I have tried to fix some of the bottlenecks by memoizing objects and values that can be re-used.

I'd like to hear what you think about this approach. According to the Blackfire profiler the response was 2x faster for a large query and 1.5x faster for one I use in my app.
You can check out my fork here: https://github.com/johanobergman/graphql-php

Grab ObjectType's name and field from request's query string.

Is there an easy/efficient way to get the ObjectType's name and Field from the query string? I want to wrap my requests in some middleware based on these, but I haven't found an easy way to get access to them.

For example, if my server was sent the following query:

{
  userQuery(email: "[email protected]") {
    id
    firstName
    lastName
  }
}

I am trying to determine if this is a Query/Mutation/Subscription Type (query in this example) and the name of the ObjectType's field (userQuery in this example). Any help would be appreciated!!

trouble with a simple example

It throws

\nFatal error: Object does not implement ArrayAccess in graphql-php/src/Type/Definition/FieldDefinition.php on line 89

Code:

        $queryType = new ObjectType([
            'name'  => 'Query',
            'fields'=> [
                'today' => [
                    'type'  => Type::string(),
                    'resolve'   => function($value, $args, $info)
                    {
                        return date('Y-m-d H:ia');
                    }
                ]
            ]
        ]);

        $schema = new Schema($queryType, null);

        try {
            // Define your schema:
            $this->result = GraphQL::execute(
                $schema,
                $this->query,
                /* $rootValue */ null,
                null,
                null
            );
        } catch (Exception $exception) {
            $this->result = [
                'errors' => [
                    ['message' => $exception->getMessage()]
                ]
            ];
        }

Request Query used was:

query try{
    today {
    }
}

Thanks!

Infinite loop when using recursive types and interfaces

tl;dr

Splitting ObjectType#initialize in two methods would solve the issue.

Details

When using recursive types with interfaces InterfaceType::addImplementationToInterfaces, ObjectType#initialize and ObjectType#getInterfaces result in an infinite loop. Using the same implementation as the JS version would solve the issue since getInterfaces would not trigger getFields.

Allow defining types using name

Allow following definition form (in addition to existing):

'fields' => [
   'id' => 'Id!',
   'author' => 'User',
   'mentions' => '[Mention!]',
   'totalCommentCount' => 'Int',
   'comments' => [
       'type' =>'[Comment!]',
       'args' => [
           'after' => [
               'type' => 'Id',
               'description' => 'Load all comments listed after given comment ID'
           ],
           'limit' => [
               'type' => 'Int',
               'defaultValue' => 5
           ]
       ]
    ]
];

It opens up path to schema serialization and constant arrays for schema definitions, which may be useful for future optimizations. Also it opens up path to defining schema using GraphQL schema language.

Obviously actual loading of type by name has to be delegated to user-land code (will likely add new option to schema constructor for type resolver).

Should be BC.

Introduce query plan as a replacement for ResolveInfo::getFieldSelection

Currently we have ResolveInfo::getFieldSelection() to do simple look-aheads. But it is too limited for real-world scenarios and provides little help when resolving field of union or interface type. Better tool has to address more use-cases. Basically it should provide convenient interface to answer following questions:

  1. What sub-fields were requested (regardless of fragment types)?
  2. What types were referenced by fragments?
  3. What sub-fields were requested for given type?
  4. What args/directives were set for given field?

Current getFieldSelection only answers question 1.

The syntax for this could be something like this:

function resolve($value, $args, $context, ResolveInfo $info) {
    $queryPlan = $info->lookAhead();

    // Answers #1:
    $fields = $queryPlan->subFields();
    $deepFieldRequested = $queryPlan->has(['nested', 'deeper', 'evenDeeper']);

    // Answers #2:
    $types = $queryPlan->referencedTypes();

    // Answers #3:
    $typeSpecificFields = $queryPlan->subFields('TypeReferencedByFragment');
}

This needs further design with regards to nested syntax + things may get quite complicated for type-dependent deep fields.

How to tackle relay connection, pagination, etc

As the title suggests, any ideas here?

Im almost at a loss at where to start, im using the laravel wrapper package, but neither this or the laravel project reference connection types, or how you would go about creating them?

Im guessing i could do it through the type system, but wanted to check if ive missed some docs somehwere that could help me out.

Question about Interfaces

Thank you very much for this great library.

I've got a question about Interfaces and validation

To play nice with relay it seems easier to follow the "node / viewer" pattern.

So for example a single entry point for all characters ( the node query ) could be implemented like this

return [
            'name' => 'Query',
            'fields' => [
                'character' => [
                    'type' => $characterInterface,
                    'args' => [
                        'id' => [
                            'name' => 'id',
                            'description' => 'global id of the character',
                            'type' => Type::nonNull(Type::string())
                        ]
                    ],
                    'resolve' => function ($root, $args) {
                        return //.. get character by global id
                    }
                ]
                //...
            ]
        ];

Then we rely on the resolveType function of our character interface to return a droid or a human type.

So far so good!

But if I want to add a field that only exists for droids let say "modelNumber" I run into a validation problem, DocumentValidator fails as it only checks the fields of the interface, and not the fields of my resolved type. Is this a bug ?

Faulty result due to memoized results

I have a BIG problem with memoized results, in this example with memoizing on I get faulty result on the leaf node:

Query:

{
  surveys(school_category:SCHOOL) {
    nid
    modules {
      survey
    }
  }
}

Faulty result, survey in each module should match the nid from the survey.

{
  "data": {
    "surveys": [
      {
        "nid": 85,
        "modules": [
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          }
        ]
      },
      {
        "nid": 707,
        "modules": [
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          }
        ]
      }
    ]
  }
}

And if I turn off memoization (Executor.php#L366-L372) I get the correct result:

{
  "data": {
    "surveys": [
      {
        "nid": 85,
        "modules": [
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          },
          {
            "survey": 85
          }
        ]
      },
      {
        "nid": 707,
        "modules": [
          {
            "survey": 707
          },
          {
            "survey": 707
          },
          {
            "survey": 707
          },
          {
            "survey": 707
          },
          {
            "survey": 707
          },
          {
            "survey": 707
          },
          {
            "survey": 707
          }
        ]
      }
    ]
  }
}

I'm not sure it's safe to memoize using the AST location and fieldname, my recommendation is to remove this performance optimization now until someone figures out how to look at the parent if that is different than previously memoized, but also that doesn't take into account if say any contextual parameter has changed. Say the user is added in some level of the graph and passed down, although atm it doesn't seem to be possible to reference the context in the resolvers to be able to add stuff (this works in the JavaScript implementation, context is passed as the third parameter). But that seems like another issue.

Add error to context from resolver

Hi,

Say I have a query:

query GracefulFailure {
    user {
        nullableFieldWithFailure
        name
    }
}
{
    data: {
        user: {
            nullableFieldWithFailure: null
            name: 'Andreas'
        }
    },
    error: [
        {
            message: "Some error message provided by me",
            locations: [
                {
                    column: 3,
                    line: 2
                }
            ]
        }
    ]
}

It is my current understanding that the resolvers only get an array representation of the context. The context is therefore passed by value and adding an error to it will be pointless.

It seems like the suggested way of adding errors to a response is by throwing an exception in the resolver. The problem with this approach is that it would stop the query execution.

Is there currently a way to add a custom error from a resolver without stopping query execution?

Related issue: #29

Update graphql spec to April2016

There is a new version of the GraphQL spec April2016.

It changed some parts in the introspection.
I might have time to open a PR for this, but probably at earliest in two weeks.

Fatal Error after last commit

Hi,

First of all, let me thank you for this great library!

We're getting a Fatal error when using graphql-php after last commit, yesterday it works fine.

PHP Deprecated: GraphQL\Schema constructor expects config object now instead of types passed as arguments. See #36 in /var/www/tnc2016/vendor/webonyx/graphql-php/src/Schema.php on line 62
PHP Fatal error: Class 'PHPUnit_Framework_TestCase' not found in /var/www/tnc2016/vendor/webonyx/graphql-php/src/Validator/Rules/LoneAnonymousOperation.php on line 18

Please contact us if you want more info on reproducing this bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.