overblog / graphqlbundle Goto Github PK
View Code? Open in Web Editor NEWThis bundle provides tools to build a complete GraphQL API server in your Symfony App.
License: MIT License
This bundle provides tools to build a complete GraphQL API server in your Symfony App.
License: MIT License
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | no |
Version/Branch | 0.8.0 |
Is there a way to upload files through graphql?
Does the bundle manage multipart request?
Here is a related proposal for Apollo: apollographql/apollo#65.
I'm trying to adapt your symfony bundle to create a graphql interface for our game (lotgd/core). Your readme mentions a bunch of files to get an example ready. Some of them have a filename associated with them while all yml files below "Relay" do not. Where should they go? Is there a fully working example somewhere?
The following should throw an error or raise a warning.
Foo:
type: object
config:
fields:
a: {type: String}
a: {type: Int}
Hello,
As GraphQL client, we use actually Apollo, which is more flexible. So we doesn't need to use Relay specificities. For example, we doesn't want to use "relay-mutation-input" and "relay-mutation-payload" for mutations.
But actually, it doesn't work. It seems that any configuration I put in payload, the returned object need a clientMutationId
:
{
"code": 500,
"message": "Neither the property \"clientMutationId\" nor one of the methods \"addClientMutationId()\"/\"removeClientMutationId()\", \"setClientMutationId()\", \"clientMutationId()\", \"__set()\" or \"__call()\" exist and have public access in class \"Page\".",
"errors": null
}
Here is my configuration:
Mutation:
type: object
config:
fields:
createPage:
builder: Mutation
builderConfig:
inputType: 'pageMutationInput'
payloadType: 'Page!' #Here I try many things as directly the Page object or pageMutationPayload
mutateAndGetPayload: |
@=service("page_manager").create(
service("form.factory")
.createNamed(null, "PageType")
.submit(args['input']).getData()
)
pageMutationInput:
type: input-object
config:
fields:
path:
type: 'String'
description: 'Page url.'
view_id:
type: 'Int!'
description: 'View ID.'
pageMutationPayload:
type: input-object # Is there another type that suits best ?
config:
fields:
page: { type: 'Page!' }
And here is my mutation call:
mutation CreatePage {
createPage(input: {view_id: 1, path: "myPage1.html"}) {
id
path
view {
id
}
}
}
As a subsidiary question: The manager needs to get a object of type "Page" , so i use Form to create it with arguments from mutation. Is there something easier to configure for mutateAndGetPayload
property?
i didn't run a graphql app in production yet, but i would like to know if it's possible to do http caching for graphql with symfony,
normally post requests are not cachable, and symfony is heavy compared to frameworks like express, which can lead to performance issues,
will symfony methods like $response->setSharedMaxAge(3600); work?
varnish/fastly can be configured to cache post requests, but i'm not sure if it would be a great idea.
and what about the symfony proxy ?
Unless I do something wrong, when I send data in a request body Parser
seems to lose it. See what happens with passed $data
here: https://github.com/overblog/GraphQLBundle/blob/master/Request/Parser.php#L82
If I want to apply pagination to some objects, the better way seems to be compatible with Relay.
I have read all specifications about relay, and seen that you have already implemented Connections and Nodes (this last one seems not to be mandatory, but hardly advise).
I think i must use ConnectionBuilder::connectionFromArraySlice
directly, with the result of a query to my database (with doctrine) and the arguments (first, after, etc.). Must i pass something special like total number of entities ?
I have read too a discussion about adding arguments for filtering/ordering. graphql/graphql-relay-js#20
Have you some advices for this ?
I'm trying to understand core concepts of this bundle.
Could you please validate or invalidate my knowledge about it please ?
First, overblog/GraphQLBundle does not use directly persistence layer (or doctrine service - different from https://github.com/4rthem/graphql-mapper (-bundle) that it seems hardly couple with Doctrine). It uses services as resolver to fetch data (from database using doctrine or not, in memory, etc.).
In code examples, where it is called $humans = StarWarsData::humans();
, I had to replace this by my entity repository for exemple.
In resolveFriend methods, I could replace StarWarsData::getFriends($character);
by $character->getFriends()
in traditional Symfony/Entity/Doctrine way.
As soon as i have a property with a listOf personal type, defining a object, i have to set a resolver, to tell bundle how to retreive data.
If I would like to expose the full list of my Characters, i declare the following Query object:
# This implements the following type system shorthand:
# type Query {
# characters(limit: Int, offset: Int, orderBy: String): [Character]
# }
#
Query:
type: object
config:
description: "Full list of characters in the Star Wars universe."
fields:
characters:
type: "[Character]"
args:
limit:
description: "If omitted,return 10 characters maximum"
type: "Int"
offset:
description: "If omitted, begin at 0"
type: "Int"
orderBy:
description: "If omitted, no sort applied"
type: "String"
resolve: "@=service('acme_bundle.my_service').find([args])"
I set a different resolve expression to be sure to understand the way to use it.
Thanks for your help
See title. While trying to use graphiql, all queries failed to give any meaningful answer except html source code. Only after copying the html code, storing it in a file and replacing all \n with real line breaks revealed that the error message is
Variables are invalid JSON
400 Bad Request - BadRequestHttpException
This error is in principle 2 bugs:
i have an issue with setting up the bundle,
my app has many bundles one of them is named graphql bundle, and in Resources/config i created a schema Query.types.yml
and in app/config/config.yml
overblog_graphql:
definitions:
schema:
query: Query
mutation: ~
in graphiql i get an error with
Unknown type with alias "query" (verified service tag) (internal 500)
i don't know if i missed something in the documentation like defining the path of the bundle,
and i would also like if it's possible to set the path of the schema manually no mather where the schema is , which would be easy to migrate for symfony 4
Q | A |
---|---|
Bug report? | yes/no |
Feature request? | yes/no |
BC Break report? | yes/no |
RFC? | yes/no |
Version/Branch | x.y.z |
Defining mutations currently requires the definition of 3 blocks: the builder, the input and the payload. This proposed syntax simplifies the definition and is easier to understand (in my opinion):
Mutation:
type: object
config:
fields:
introduceShip:
builder: IntroduceShipMutation # Here is a BC break.
# Since we haven't reach 1.0, it is not an issue.
IntroduceShipMutation:
type: relay-mutation
config:
inputFields: # Define the input
shipName: {type: String!}
factionId: {type: ID!}
outputFields: # Define the payload
ship: {type: Ship}
faction: {type: Faction}
mutateAndGetPayload: "@=resolve('my_mutator', [value])"
mutateAndGetPayload
replaces the resolve
on introduceShip
.
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | no |
Version/Branch | ^0.7 |
I came to an idea, when I was searching for answers. I wanted to know how you modified types like relay-mutation-payload
without the requirement to provide build
& builderConfig
. I found the definition file, but the only way I knew to use it, is to define a builder
& builderConfig
. Then I found this.
You basically pass some parts of the fields configuration to a given builder as its config.
It looks hard-coded to me - I could not find a way to do it myself just via extension configuration.
Then came the idea:
Why not melt the builder concept and what you do in \Overblog\GraphQLBundle\DependencyInjection\TypesConfiguration
into a single concept?
Basically: field Type = builder alias.
Maybe even drop the naming builder
and just keep the definition
which would make more sense with the unification.
Additionally I'v noticed that you can also map args in field builder. So far I did not find any use case for the args builder. Is there any reason for it to exist at all? The less concepts to achieve the same results, the easier to grok ! :)
Advantages could be:
relay-mutation-payload
required anymorerelay-mutation-payload
are currently defined.Seems like it's not allowed to define it in the field config.
Only array is accepted in released version.
This should ease the management of graphiql version (thanks to @ooflorent #50)
Hi! First of all... really great library! Awesome work.
I have a question about the value
a resolver receives.
On the User
type definition I have a contacts
field defined which resolves to an array of Contact
s:
User:
type: object
contacts:
type: "[Contact]"
description: "The contacts the user can impersonate."
resolve: '@=resolver("user_contacts", [value, args])'
With the Contact
type definition with a account
field.
Contact:
type: object
config:
fields:
account:
type: "Account"
description: "Account of the contact"
resolve: '@=resolver("contact_account", [value, args])'
When the Account is resolved, the value that is passed to the resolver is the Contact
casted to an array instead of a Contact
object. When I resolve the account not via the contacts
field but via another field of type Contact
(not [Contact]
) I get a Contact
object.
Any hints why the value
is an array in the case of the [Contact]
type?
Q | A |
---|---|
Bug report? | no |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Version/Branch | master |
Is it possible to get the requested fields inside the resolver? I have a field that takes a heavy calculation and I only want to execute that calculation when the user actually queries for it.
For example:
query {
event(id: "1") {
id
totalNumberOfUsers
}
}
The calculation of totalNumberOfUsers
is heavy and I only want to execute that when the user is actually querying for that information.
Any ideas?
I checked all possible values I could pass to my resolver:
@=resolver('event', [args, value, info, context])
But none contain the information needed.
Q | A |
---|---|
Bug report? | maybe |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Version/Branch | master |
First of all, thanks so much for the work on all these bundles. Works really well! ๐
I'm using overblog/graphql-bundle
and overblog/dataloader-bundle
on master
with the configuration described in this ticket.
When implementing the load
method in the data loader I'm returning a list of objects in the order of the keys
. Sometimes it can happen that a key
is requested for a non-existing object.
I'm using the following helper:
public static function orderObjectsById(array $ids, array $unorderedObjects, string $idField = 'id') : array
{
$idToIndexMap = array_flip(array_column($unorderedObjects, $idField));
$objects = [];
foreach ($ids as $id) {
if (false === isset($idToIndexMap[$id])) {
$objects[] = new UserWarning("Object with id '$id' not found");
} else {
$objects[] = $unorderedObjects[$idToIndexMap[$id]];
}
}
return $objects;
}
I thought I'll place a UserWarning
for the object that is missing. When debugging I saw that this results in the promise for only this object being rejected which is perfect.
For some reason the data
that is passed to the Executor::executeQuery
promise is null
. I would expect that it shows all data that is available, except the missing object.
Response:
{
"data": [],
"extensions": {
"warnings": [
{
"message": "Not found",
"locations": [
{
"line": 100,
"column": 3
}
],
"path": [
"test"
]
}
]
}
}
How could I debug this further? I'm having troubles to find how the $data
gets to this part of the code.
Thanks a lot!
Hi!
Relay root queries does not support more than one argument, at least in Facebook's RelayReact library.
To avoid this limitation I need to wrap the query arguments in other args builder that extends ConnectionArgs adding then my custom arguments. In bundle's documentation this chapter is marked as TODO.
So, is it possible to make a simple example with this topic?
Thank in advance!
See title.
I'd like to extend the functionality of a graphql schema by allowing modules to add their own types. One possibility would be to move the files to AppBundle/resources/graphql/{module}/*.types.yml or link them from there. Doctrine can be configured with additional annotation directories. Is there something similar to this in GraphQLBundle?
I would like to be able to handle binary files coming in GraphQL requests. Currently Parser
collects only POST data: https://github.com/overblog/GraphQLBundle/blob/master/Request/Parser.php#L63.
Also related: what would be the best GraphQL type to map to uploaded file? Is String sufficient?
When using nested routes in Relay, multiple queries are required to render the application. Relay default network layer receives the requests as an array but runs then concurrently. Because of query structure, it is really hard to combine them in a single query (fragment names and variables can create conflicts).
An alternate solution is to support query batching. Instead of receiving a json request containing the query and the variables, the server should be able to decode an array of requests.
// Normal query
{query: "query q{user(id:$id){id}}", variables: {id: 1}}
// Batch alternative
[
{query: "query q{user(id:$id){id}}", variables: {id: 1}},
{query: "query q{user(id:$id){id}}", variables: {id: 2}},
]
// Combine approach (too hard to implement)
{query: "query q{u0:user(id:$id0){id}u1:user(id:$id1){id}}", variables: {id0: 1, id1: 2}}
Hi!
First of all, nice bundle guys! ;)
We are using it intensively in our projects and we found a bug related with exceptions catches. When we're executing a mutation and if our logic throws an exception your error handler listener builds a proper response to serve, but always returns a 200 statusCode. This is very frustrating when we consume the graphql from for example React client app, because it is not possible to discriminate for statusCode.
๐ Need better documentation, README.md is becoming to huge .
We can use https://readthedocs.org/ to do that...
I have following example:
{
company(id: "123") {
name,
directors(active: true) {
name
}
}
so problem is once we call the nested directors
in the resolver we pass just the [value]
which is the company data but the arguments are skipped. This is a valid GraphQL query though.
Implement a rule validator like this one
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | yes |
Version/Branch | x.y.z |
Setting access expression at query level, and prevent database access if user doesnt have to those queries.
Q | A |
---|---|
Bug report? | no |
Feature request? | no |
BC Break report? | no |
RFC? | yes |
Version/Branch | x.y.z |
Hello,
We want to use this bundle but our project is still on Symfony 2.6. For which reason Symfony 2.7 is required?
Hello,
I have two bundles that are standalone (for example UserBundle and ProductBundle).
Each one define their own graphql Query types.
When I want to use those two bundle in the main application, i get a conflict on the Query.types.yml, as it is defined twice.
Do you have an advice to resolve this conflict ?
Do I need to define only one Query type in main app ? What about functional tests in this case in bundles ?
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | no |
Version/Branch | master |
Hi!
I am using GraphQL to query a list of objects ("sport"). The query has a timestamp input argument "date". This works fine for the main sport object that resolves correctly. However, I need to figure out how to pass the date argument down to the matchcounts resolver. My actual code not works, the args input in resolveMatchCounts method is allways empty. I am a newbie about GraphQL... Thank You.
query sports {
sports (date: 1477785600){
id
name
matchCounts {
finished
scheduled
}
}
}
Query.types.yml:
Query:
type: object
config:
fields:
sports:
type: "[Sport]"
args:
date:
description: "timestamp"
type: "Int"
resolve: "@=resolver('sport_sports', [args])"
Sport.type.yml:
Sport:
type: object
config:
description: "Sport"
fields:
id:
type: "String"
description: "The id of the sport."
name:
type: "String"
description: "The name of the sport."
matchCounts:
type: "MatchCounts"
description: "match counts for this sport"
resolve: "@=resolver('sport_matchcounts', [value, args])"
MatchCounts.type.yml:
MatchCounts:
type: object
config:
description: "MatchCounts"
fields:
finished:
type: "Int"
description: "Finished"
scheduled:
type: "Int"
description: "scheduled count."
Services.yml:
my.graph.resolver.sports:
class: ApiBundle\GraphQL\Resolver\SportsResolver
arguments:
- "@overblog_graphql.type_resolver"
tags:
- { name: overblog_graphql.resolver, alias: "sport_sports", method: "resolveSports" }
- { name: overblog_graphql.resolver, alias: "sport_matchcounts", method: "resolveMatchCounts" }
SportsResolver.php:
public function resolveSports($args)
{
$timestamp = isset($args['date']) ? (int)$args['date'] : time();
//args is not empty
$sportModel = $this->container->get('model.sport.sports');
$data = $sportModel->getSportsData(['timestamp' => $timestamp]);
return $data;
}
public function resolveMatchCounts($sport, $args)
{
//$args is empty :(
//print_r($args->getRawArguments());
$timestamp = isset($args['date']) ? (int)$args['date'] : time();
$sportModel = $this->container->get('model.sport.sports');
$data = $sportModel->getSportMatchCount(['timestamp' => $timestamp], $sport);
return $data;
}
From what I experience the resolver is called even if a security check for a field does not pass. A field resolver might be expensive to call and I would like to prevent it from being called by setting some access rule.
Same background as in #56 - i'd like to provide a way to extend the schema. Is there a possibility to change the schema after it's being read by the graphql bundle?
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | no |
Version/Branch | 0.7.1 |
Could the following check be adjusted, so it does not throw, when the service implements __invoke
?
ResolverTaggedServiceMappingPass::checkRequirements
protected function checkRequirements($id, array $tag)
{
parent::checkRequirements($id, $tag);
if (!isset($tag['method']) || !is_string($tag['method'])) {
throw new \InvalidArgumentException(
sprintf('Service tagged "%s" must have valid "method" argument.', $id)
);
}
}
It is similar to controllers. Some prefer creating multiple actions per controller, some a single one. For the later it saves a lot of configuration, when tag method can be omitted.
Q | A |
---|---|
Bug report? | yes |
Feature request? | yes |
BC Break report? | no |
RFC? | no |
Version/Branch | 0.6.2 |
http://webonyx.github.io/graphql-php/data-fetching/#default-field-resolver-per-type
resolveField is a feature in webonyx that allows you to define a type level resolver. You can still put a resolver on individual fields if you like, but basically you get the opportunity to define the resolver at the type level as a default.
The problem is that you alway register the default resolver for any field that doesn't have a resolver regardless of there being a parent resolveField. This is honestly perfectly acceptable behaviour but it does break the resolveField use case because of https://github.com/webonyx/graphql-php/blob/master/src/Executor/Executor.php#L622-L628
There's some tradeoffs there that I don't wanna make on your behalf. Let me know if this makes sense.
Q | A |
---|---|
Bug report? | yes |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Version/Branch | master#eed88d8e88f1fe7dea3835ab7371f146a6806543 |
When doing a valid JSON request, with a valid JSON body, a warning is thrown if the JSON body isn't valid GraphQL.
The message is Warning: mb_strlen() expects parameter 1 to be string, array given
, in file webonyx/graphql-php/src/Language/Source.php
line 24.
You can find the entire stack trace here: https://gist.github.com/pascaldevink/413fdd9d9436e138150ff14d6ae022ea
I guess there isn't enough error checking in Overblog\GraphQLBundle\Request\Parser::getParsedBody()
when it come to JSON data. In fact, I'm not sure why it is supported, I can't find any documentation on how to send data this way.
Of course, it's a warning, which will be ignored in production, but I think it should be handled properly nonetheless.
Documentation for #81
isTypeOf expression language function doesn't work since april2016 migration. UT to covers this, should be added.
Episode:
type: enum
config:
values:
NEWHOPE:
value: 4
EMPIRE:
value: 5
JEDI:
value: 6
Should be equivalent to:
Episode:
type: enum
config:
values:
NEWHOPE: 4
EMPIRE: 5
JEDI: 6
Q | A |
---|---|
Bug report? | no |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Version/Branch | 0.7.1 |
Hello,
How to define custom scalar type ?
We followed the example in test suite but in place of the date time in query response, we get this:
...
startDateTime: ["Acme\\AppBundle\\GraphQL\\Type\\DateTimeType", "serialize"]
...
If we send parameters for a mutation, the datetime in database is null.
Did we miss something ?
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | no |
Version/Branch | 0.7.1 |
When omitting alias for an resolver would implicitly set the alias to be equal the service class name, combined with this feature request, a lot of boilerplate configuration could be saved using a bundle like DunglasActionBundle. You would not need to configure any resolver services at all, as long as you implement a single resolve function per class (__invoke).
Add a feature that convert GraphQL Type System Definition:
interface Character {
id: String!
name: String
friends: [Character]
appearsIn: [Episode]
}
to config yaml file:
Character:
type: interface
config:
fields:
id:
type: "String!"
name:
type: "String"
friends:
type: "[Character]"
appearsIn:
type: "[Episode]"
Q | A |
---|---|
Bug report? | no |
Feature request? | yes |
BC Break report? | no |
RFC? | no |
Version/Branch | ^0.7.1 |
I want graphiql to send an authentication token to server. The package you use allows graphiql interface customization. For example you can add input fields into the toolbar.
Currently you use the default graphiql interface without any customization.
It would be convenient, if I could define the following configuration for an endpoint:
# app/config/config_dev.yml
# overblog_graphql.definitions.schema
authentication:
# optionally namespaced by endpoint name specified in overblog_graphql.definitions.schema
send_method: "header" # header, query-string, ...
fields: # fields to send using specified method
access-token: "myaccesstoken"
Currently you need to override/extend the default template, which is unsafe.
Hello,
I'm trying to make a query on products with a custom filter type.
Here is the base Query.types.yml
:
Query:
type: object
config:
description: "Product bundle."
fields:
getProducts:
type: "QueryProduct"
args:
filter:
description: "Product search filters."
type: "ProductFilter"
My ProductFilter.types.yml
is defined as an input-object
:
ProductFilter:
type: input-object
config:
description: "Product filters"
fields:
categoryIds:
type: "[Int]"
description: "Category filter."
highLight:
type: "ProductHighLightFilter"
description: "Highlight product filter."
...
price:
type: "RangeFilter"
description: "Product price filter."
...
And finally my RangeFilter.types.yml
, as an input-object
too:
RangeFilter:
type: input-object
config:
description: "Range filter"
fields:
min:
type: "Float"
description: "Min value."
max:
type: "Float"
description: "Max value."
When I run the tests (with Codeception) just after initialize the app (clear cache, install database and load fixtures, create admin user), i get randomly the following error Class 'Overblog\GraphQLBundle\__DEFINITIONS__\RangeFilterType' not found
.
I get this only for RangerFilter, that is an "inline-object" too.
Have you an idea where the error come from ? Am i using the "inline-object" correctly ?
Q | A |
---|---|
Bug report? | yes |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Version/Branch | 0.8.0 |
Wen I open the graphiql provided by this bundle, I have the following issues:
Researching I found the reason.
The graphQLFetcher
updates the toolbar DOM here (GraphQLBundle)
The WP toolbar inject an initializer script here (WebProfilerBundle)
The initialization includes:
Problem:
graphQLFetcher
the events are not attached on the new DOMQ | A |
---|---|
Bug report? | yes |
Feature request? | no |
BC Break report? | no |
RFC? | no |
Version/Branch | 0.8.0 |
Hi,
we get a few deprecation warning on for the use of ArrayParserCache
on Symfony 3.
They were easy to fix: master...madarco:master
However, I don't know if those break BC with Symfony 2.
Hope this could help others with the same issue.
Marco D'Alia
Hi :-),
I am trying to install this bundle following the instructions but when I go to localhost/graphiql in doc section I get html document from localhost/. Sorry if its a dumb question :/ but I am a newbie with graphQL
My current sf version: 3.2.7
# app/config/graphql/Query.types.yml
Query:
type: object
config:
description: "A humanoid creature in the Star Wars universe."
fields:
user:
type: "User"
resolve: "@=resolver('myresolver')"
# app/config/graphql/User.types.yml
User:
type: object
config:
description: "User"
fields:
id:
type: "String!"
name:
type: "String"
# app/config/services.yml
services:
myresolver:
class: AppBundle\Service\MyResolver
tags:
- { name: overblog_graphql.resolver, alias: myresolver, method: resolveMyResolver }
# src/AppBundle/Service/MyResolver.php
namespace AppBundle\Service;
class MyResolver
{
public function resolveMyResolver()
{
return ['id' => 1, 'name' => 'Luke'];
}
}
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.