Add Custom WP GraphQL Types and mutations,
February 06, 2019
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.