/

Mutations API Reference

Learn how to register mutations and extend existing mutations


About Mutations

Mutations in GraphQL signify that some data is changing. Other than the keyword mutation, they are technically identical to Queries.

Register new Mutation

To register a mutation to the Schema, use the register_graphql_mutation function within the graphql_register_types action.

The register_graphql_mutation function takes 2 arguments:

  • \$name: The name of the mutation (createComment, etc)
  • \$config: An array to configure the mutation
    • inputFields: inputFields: The input fields for the mutation
    • outputFields: The output fields for the mutation (what can be asked for in response)
    • mutateAndGetPayload: How the mutation should resolve

Here's a basic example of registering a mutation using PHP:

# This is the action that is executed as the GraphQL Schema is being built.
add_action( 'graphql_register_types', function() {

	# This function registers a mutation to the Schema.
	# The first argument, in this case `exampleMutation`, is the name of the mutation in the Schema
	# The second argument is an array to configure the mutation.
	# The config array accepts 3 key/value pairs for: inputFields, outputFields and mutateAndGetPayload.
	register_graphql_mutation( 'exampleMutation', [

		# inputFields expects an array of Fields to be used for inputting values to the mutation
		'inputFields'         => [
			'exampleInput' => [
				'type' => 'String',
				'description' => __( 'Description of the input field', 'your-textdomain' ),
			]
		],

		# outputFields expects an array of fields that can be asked for in response to the mutation
		# the resolve function is optional, but can be useful if the mutateAndPayload doesn't return an array
		# with the same key(s) as the outputFields
		'outputFields'        => [
			'exampleOutput' => [
				'type' => 'String',
				'description' => __( 'Description of the output field', 'your-textdomain' ),
				'resolve' => function( $payload, $args, $context, $info ) {
                   			return isset( $payload['exampleOutput'] ) ? $payload['exampleOutput'] : null;
				}
			]
		],

		# mutateAndGetPayload expects a function, and the function gets passed the $input, $context, and $info
		# the function should return enough info for the outputFields to resolve with
		'mutateAndGetPayload' => function( $input, $context, $info ) {
			// Do any logic here to sanitize the input, check user capabilities, etc
			$exampleOutput = null;
			if ( ! empty( $input['exampleInput'] ) ) {
				$exampleOutput = 'Your input was: ' . $input['exampleInput'];
			}
			return [
				'exampleOutput' => $exampleOutput,
			];
		}
	] );

} );

Registering the above mutation would allow for the following mutation to be executed

mutation {
	exampleMutation(
		input: { clientMutationId: "example", exampleInput: "Test..." }
	) {
		clientMutationId
		exampleOutput
	}
}

And the following response would be provided:

{
	"data": {
		"exampleMutation": {
			"clientMutationId": "example",
			"exampleOutput": "Your input was: Test..."
		}
	}
}

Extend existing mutations

Extending mutation for post

	/**
		* Run an action after the additional data has been updated. This is a great spot to hook into to
		* update additional data related to postObjects, such as setting relationships, updating additional postmeta,
		* or sending emails to Kevin. . .whatever you need to do with the postObject.
		*
		* @param int $post_id The ID of the postObject being mutated
		* @param array $input The input for the mutation
		* @param \WP_Post_Type $post_type_object The Post Type Object for the type of post being mutated
		* @param string $mutation_name The name of the mutation (ex: create, update, delete)
		* @param AppContext $context The AppContext passed down to all resolvers
		* @param ResolveInfo $info The ResolveInfo passed down to all resolvers
		* @param string $intended_post_status The intended post_status the post should have according to the mutation input
		* @param string $default_post_status The default status posts should use if an intended status wasn't set
		*/

	add_action( 'graphql_post_object_mutation_update_additional_data', 'graphql_register_edit_mutation', 10, 5 );

	function graphql_register_edit_mutation( $post_id, $input, $mutation_name, $context, $info ) {
		// Consider other sanitization if necessary and validation such as which
		// user role/capability should be able to insert this value, etc.
		if ( ! empty( $input['example'] ) ) {
			update_post_meta( $post_id, 'example', $input['example'] );
		}
	}

Extending mutation for user

	/**
		* Run an action after the additional data has been updated. This is a great spot to hook into to
		* update additional data related to users, such as setting relationships, updating additional usermeta,
		* or sending emails to Kevin... whatever you need to do with the userObject.
		*
		* @param int $user_id The ID of the user being mutated
		* @param array $input The input for the mutation
		* @param string $mutation_name The name of the mutation (ex: create, update, delete)
		* @param AppContext $context The AppContext passed down the resolve tree
		* @param ResolveInfo $info The ResolveInfo passed down the Resolve Tree
		*/

	add_action( 'graphql_user_object_mutation_update_additional_data', 'graphql_register_user_mutation', 10, 5 );

	function graphql_register_user_mutation( $user_id, $input, $mutation_name, $context, $info ) {
		if ( isset( $input['hobbies'] ) ) {
			// Consider other sanitization if necessary and validation such as which
			// user role/capability should be able to insert this value, etc.
			update_user_meta( $user_id, 'hobbies', $input['hobbies'] );
		}
	}

Edit on GitHub

Mutations API Reference

  • About Mutations
  • Register new Mutation
  • Extend existing mutations

Edit on GitHub

Discuss on Spectrum