INTRO:
Problem: Traditional RESTful web services are not so efficient in some use case:
- Sometimes we want to fetch part of an entity’s data. But web service only returns a complete set of data.
- Sometimes we want to fetch many related entities. But web service only accesses a single entity. So we have to make many round trips.
- If web service (endpoint, resources’ schema) changes, client code has to change as well.
And vice-versa, if the client requires a different set of data, we should change web service to support that, or at least to improve the outcome.
GraphQL solution:
- Allows clients to define the structure of the data required, and exactly the same structure of the data is returned from the server. Therefore it prevents the excessively large amounts of data from being returned.
- GraphQL is not dealing with dedicated resources. Instead, everything is regarded as a graph and connected.
You can combine different entities in one query and you are able to specify which attributes should be included in the response on every level.
- Single endpoint.
Client controls the query part – the query matches exactly the response. You do not need to read the documentation or run the request to know the response structure. Webservice and client can be developed parallel and independently at some extends.
About GraphQL: (more details)
- GraphQL is an open-source data query and manipulation language, and a runtime for fulfilling queries with existing data.
- Developed by Facebook.
- On 9th February 2018, the Schema Definition Language (SDL) was made part of the specification
DETAILS
1. Server
We need to install a GraphQL server to serve data “graphQL way”. It’s available for multiple languages, including Haskell, JavaScript, Python,[10] Ruby, Java, C#, Scala, Go, Elixir,[11] Erlang, PHP, R, and Clojure
- PHP: https://github.com/webonyx/graphql-php or https://github.com/leocavalcante/siler
- Nodejs: https://github.com/graphql/graphql-js/ or https://github.com/graphql/express-graphql (for working with express.js)
Schema:
- In order to describe the data that available to be queried, in the server above, we need to define our schema (types system).
- GraphQL has its own language to write Schemas: The Schema Definition Language (SDL). It’s language-agnostic, so you can use the same set of definition in GraphQL server written by PHP, Nodejs, Python…
- If you want to quickly build & test a schema with Nodejs, go to this in-browser GraphQL server playground
- Schema SDL example:
# hero is an object type type hero { ID: ID! # ! mean server will always return a non-null value for ID and name when fetching hero name: String! # ID and name are fields of scalar type appearsIn: [movie]! # these fields return a non-null list of movie objects } # movie is an object type type movie { ID: ID! # ID is a special scalar type name: String! character(OrderOfAppearance: Int): [hero] # id argument for nested fields } # one query object type is required for a schema, that describe what data can be fetched from client type queryRootType { # Get one hero item hero(id: ID!): hero # accept id argument # Get all hero items allHeros: [hero!]! #get movie movie(id: ID!): [movie] } # one mutation object type, optional for a schema, that describes what data can be sent from the client type mutationRootType { addHero(id: ID!, name: String!, appearsIn: movie): hero! # this's the required field removeHero(id: ID!): hero! } # only one schema definition for each schema schema { query: queryRootType mutation: mutationRootType }
In the server above, write “resolver” to map schema types to actually code that gets data.
Please see PHP tutorial here
Recommendation:
- GraphQL is typically served over HTTP via a single endpoint which expresses the full set of capabilities of the service
- Return JSON (with gzip)
2. Clients:
There are many clients writing in many languages.
Below is some examples using curl, in order to show the most basic form of GraphQL query:
- Search a single hero by id:
curl <your-endpoint> -d '{"query": "query { hero(id: 1) }" }'
- Fetch all hero names:
curl <your-endpoint> -d '{"query": "query { allHeros{name} }" }'
- There are special types “__schema” and “__type” that enable introspection of the schema:
curl <your-endpoint> -d '{"query": "query { __schema{types{kind, name, possibleTypes{name}}}}" }' curl <your-endpoint> -d '{"query": "query { __type(name:\"hero\"){name, fields{name} } }" }
- Allows send variables in “variables” field of our payload:
curl <your-endpoint> -d '{"query": "query($id:ID) { hero(id: $id) }", "variables": {"id":1} }'
Check out our demo here
Comment down below if you have any question or contact us via email for free consultation. Don’t forget to share & subscribe to our blog!
Chuong Nguyen
References
https://medium.com/codingthesmartway-com-blog/rest-vs-graphql-418eac2e3083
https://en.wikipedia.org/wiki/GraphQL
https://graphql.org
https://blog.apollographql.com/three-ways-to-represent-your-graphql-schema-a41f4175100d
https://facebook.github.io/graphql/draft/