You might have heard of a new sheriff in town: GraphQL. And then wondered how you could use it with *insert your non-JS language here*.

Sick montage skills here

TLDR;

If you are very lazy and just want a solution, here is my demo project, I’ll try to keep it updated: https://github.com/florentdestremau/graphql-example

What is GraphQL? Small reminder

Quick memo for those who don’t know what I’m talking about: GraphQL is a query language designed by Facebook to represent a modern way to communicated data between your front-end and back-end. For example if you wanted to query for the latest article from a blog, you’d write something like this as a front-end query

articles(limit: 10) {

id

title

excerpt

categories {

id

name

}

comments(limit: 3) {

id

author {

id

name

}

content

}

}

Did you see what happened here? A whole hierarchy of information was requested in a single request, and now we have all the information needed to display a whole bunch of stuff:

article titles with their link

the article categories with links too

the first articles’ comments, with a click-able link to the user’s profile

the content of the first 3 comments on the article.

So this is the very basic usage of GraphQL. But it’s only half of the implementation, you still need the back-end to handle the query interpretation and then return the actual data.

The back-end implementation in Symfony

If you are convinced by the simplicity and power of this type of query from the front-end (I sure am!), you probably wonder how it turns out in your back-end. So now is the time for me to announce that I am a Symfony developper and thus, while Facebook gave plenty of tools for NodeJS lovers, I had to rely on other libraries.

Meet youshido/graphql-bundle, the bundle that makes it all easy for you !

N ote: there is an php port linked on the GraphQL website but at the time I was looking for a Symfony implementation, the youshido bundle was a better option for me, feel free to try the PHP library out !

The objective of this article is to explain how we use this bundle to easily set up you GraphQL API for a simple use: front-end widgets. The YoushidoGraphQLBundle provides several classes to structure your GraphQL query tree.

Youshido\GraphQL\Schema\AbstractSchema to set up your basic architecture

to set up your basic architecture Youshido\GraphQL\Type\Object\AbstractObjectType to set up query-out formatting (in all of my use cases I used the AbstractObjectType rather than the AbstractType )

to set up query-out formatting (in all of my use cases I used the rather than the ) Youshido\GraphQLBundle\Field\AbstractContainerAwareField to set up any query-in arguments and actions

For example you will have a tree structure like this:

Schema

- Query

- ArticlesField

- CommentsField

- UsersField

- CategoriesField

- Mutations

- PostArticleField

And each of these Fields will respectively return ArticleType , CommentType , UserType , CategoryType , or more exactly a ListType of these.

The Fields

Here is what a simple ArticlesField would look like.

class ArticlesField extends AbstractContainerAwareField

{

public function resolve($value, array $args, ResolveInfo $info)

{

return $this->container->get('doctrine.orm.entity_manager')->getRepository(Article::class)->findAll();

} public function getType()

{

return new ListType(new ArticleType());

}

}

Notice the 2 key functions here.

resolve is the "controller", where you have access to the container and can call any service to retrieve the DATA

is the "controller", where you have access to the container and can call any service to retrieve the DATA getType is the "template", you express what type of return format you allow for the GraphQL schema to have. We’ll get to that further down.

There is an extra function that you can use, it’s the build function:

public function build(FieldConfig $config)

{

$config->addArguments(

[

'published' => new BooleanType(),

]

);

}

This argument is exposed to the query, for instance you could query only articles that are published

articles(published: true) {

id

title

body

}

And then you can update your resolver:

public function resolve($value, array $args, ResolveInfo $info)

{

return $this->container

->get('doctrine.orm.entity_manager')

->getRepository(Article::class)

->findBy([

'published' => $args['published'],

]);

}

And there you go, filtered results !

The Types

So this was the “controller” part of the query, and now let’s get to the “templating” part. The Types (kind of a unfortunate naming, in my opinion, with the form Types as well, but hey I didn’t write it ¯\_(ツ)_/¯) are the classes that defines the JSON output for the file. Here is an example of what the ArticleType would be.

class ArticleType extends AbstractObjectType

{

public function build($config)

{

$config->addFields(

[

'id' => new IdType(),

'title' => new StringType(),

'body' => new StringType(),

'categories' => new ListType(new CategoryType()),

]

);

}

}

This way you define what fields are available to retrieve. Now this is a simple version, but you can add custom fields that require a bit more of an assistance. For instance to display the phone number of a user I would need to use the container:

As you can see the ResolveInfo entity has access to the container so you can use different services to render or simply do some logic stuff.

And there you go, a full GraphQL API!

Oh and one last thing, did I tell you that you had a live explorer at the /graphql/explorer ?

I actually made an API boilerplate with the bundle already installed:

Liked what you read ? Hit the 👏 button, I will write some more!