Add Custom WP GraphQL Types and mutations,

February 06, 2019

in wordpress graphql

Currently I’m working on migrating Modepilot to a modern frontend stack with next.js and GraphQL. For the backend part, there is a neat Wordpress Plugin to do all the GraphQL stuff: WP-GraphQL. While the community is amazing and super helpfull, the documentation is a bit lackluster. Lots of stuff can only be found while digging trough the source.

Let’s Change that

For my example I’ll be implementing the GraphQL Endpoints for the great wp-polls plugin. I won’t go into much details with the data fetching, I asume my readers know how to use wpdb.

Reading things

When we are done, we want the query to look something like this:

query {
  poll(id: 123) {
    id
    text
    answers {
      nodes {
        id
        text
        votes
      }
    }
  }
}

Get the poll by id, and the poll should have the fields for id, text and a list of answers.

The first part we need to do, is to implement add the GraphQL types and fields. We are using the register_graphql_object_type function. First parameter is the new field name, second paramter is an array of fields. We don’t need lots of fields for our example.

register_graphql_object_type(
  'PollAnswer',
  [
    'fields' => [
      'id' => [ 'type' => 'Int' ],
      'text' => [ 'type' => 'String' ],
      'votes'  => [ 'type' => 'Int' ],
    ]
  ]
);

register_graphql_object_type(
  'Poll',
  [
    'fields' => [
      'id' => [ 'type' => 'int' ],
      'text' => [ 'type' => 'String' ],
    ],
  ]
);

Next step is implementing the connections between the two types. Here we use the register_graphql_connection function to connect the types we defined before. From a Poll we want a connection to a list of PollAnswer objects, that can be retreived using the answers field. The data fetching happens in resolve, where we return the content of the connection field. In connectionFields we implictly define the answers field to be a list of type PollAnswer. The resolve function just returns what we get from the resolver defined earlier.

For now I didn’t need connectionsArgs, so I can’t go into detail here.

register_graphql_connection([
  'fromType'         => 'Poll',
  'toType'           => 'PollAnswer',
  'fromFieldName'    => 'answers',
  'resolve'          => function ( $source, $args, $context, $info ) {
      // add code here
      $nodes = [];

      return  [
          'nodes' => $nodes
      ];
  },
  'connectionFields' => [
      'answers' => [
          'type'        => [
              'list_of' => 'PollAnswer',
          ],
          'description' => __( 'The nodes of the connection, without the edges', 'wp-graphql' ),
          'resolve'     => function ( $source, $args, $context, $info ) {
              return  ! empty( $source['nodes'] ) ? $source['nodes'] : [];
          },
      ],
  ],
  'connectionArgs'   => [],
] );

After this is set up, we can add our new Type to the RootQuery. Using register_graphql_field we can add new fields to existing types. In our case we a field called poll add the field to the RootQuery. The third argument are the options. Options take the same data strucuture we already know from the fields in register_graphql_object_type. The difference here is the case that we add an arguments key to query by id. resolve once again is only simple data fetching. Its important to return an array with the keys we defined in register_graphql_object_type.

register_graphql_field(
    'RootQuery',
    'poll',
    [
        'type'        => 'Poll',
        'description' => 'a poll',
        'args'        => [
            'id' => [
                'type' => [
                    'non_null' => 'Int',
                ],
            ],
        ],
        'resolve' => function ( $source, array $args, $context, $info )  {
            $poll = get_poll_question( $args['id']);

            return [
                'id' => $args['id'],
                'text' => $poll,
            ];
        },
    ]
);

Und thats it, we can query our custom type.

@todo: mutation comming up.


Created with getavataaars.com

Hi, I'm Karsten!!!

I live in Munich and I work at InterNations
I like working with React and Symfony, I like to travel, call myself a sneakerhead, play lots of Destiny, and sometimes take lots of photos.
If you want to, you can follow me on Twitter, Unsplash, and GitHub