register_graphql_union_type

Given a Type Name and a `$config` array, this adds an UnionType to the TypeRegistry

register_graphql_union_type( string $type_name, array $config );

Parameters

  • $type_name (string): The unique name of the Type in the Schema. This must be unique amongst the entire Schema.
  • $config (array): Configuration for the field
    • $description (string): Description of the Union type.
    • $types (array): An array of Types that the union could return
    • $resolveType (function): A function that takes the resolving data and determines what GraphQL Type should be returned.

Source

File: access-functions.php

Example

Unions are useful when a field needs to return different Types that don’t implement a common interface.

An example of when using a Union might be good would be adding search functionality that could search across. For example, if you had a Movie Database site, you might want to have a search query return Genres (a custom taxonomy for example sake) or Movies (a custom post type for example sake) in the same list.

To do this, you would need to register a Union that could return a `Genre` or a `Movie`.

We’re going to assume that we already have a Genre Taxonomy registered to show in GraphQL, and a Movie Post Type registered to Show in GraphQL, so we can make use of the Genre and Movie Types in our Schema.

Below, is a snippet showing how to register a Union that could return a Genre or a Movie.

add_action( 'graphql_register_types', 'register_pet_union', 10, 1 );

function register_pet_union( $type_registry ) {
  register_graphql_union_type( 'GenreOrMovieUnion', [
    'typeNames'       => [ 'Genre', 'Movie' ],
    'resolveType' => function( $search_result ) use ( $type_registry ) {
      // Here we receive the object or array that's being resolved by the field
      // and we can determine what Type to return
      $type = null;

      if ( $search_result instanceof \WPGraphQL\Model\Term && $search_result->taxonomy === 'genre' ) {
        $type = 'Genre';
      } else if ( $search_result instanceof \WPGraphQL\Model\Post && $search_result->post_type === 'movie' ) {
        $type = 'Movie;
      }
      return $type;
    }
  ] );
}

This registers a Union type named GenreOrMovieUnion.

The typeNames field defines what Types from the Schema are possible to be returned. In this case, the Genre or Movie Type.

Then resolveType is the function that runs during execution to determine what Type should be returned. It accepts the resolving data, and you can use that data to determine what Type to return.

In our case, either a Post or Term would be returned to the Union, so we can check which Type it is and determine whether it’s a Taxonomy or a Post and set the return type appropriately.

Now, we can use the Union in a field.

add_action( 'graphql_register_types', function() {

 register_graphql_field( 'RootQuery', 'searchMoviesAndGenres', [
    'description' => __( 'Search across Movies and Genres', 'your-textdomain' ),
    'type' => [ 'list_of' => 'GenreOrMovieUnion' ],
    'resolve' => function() {

        // There's no easy way out of the box to search across Terms and Posts
        // So I'll leave that up to you. 
        // But, let's say you return the following payload: 

        $data = [
           new \WPGraphQL\Model\Term( get_term( $term_id ) ),
           new \WPGraphQL\Model\Post( get_post( $post_id ) ),
        ];

        return $data;
    }
 ] );
});

Now we have a searchMoviesAndGenres field on our RootQuery that returns a list of items, containing both Posts and Terms, we could now search like so:

Now, we can query like so:

{
	searchMoviesAndGenres {
		__typename
		... on Movie {
			title
			releaseDate
		}
		... on Genre {
			name
			description
		}
	}
}

And we’ll receive the following data:

{
	"data": {
		"searchMoviesAndGenres": [
			{
				"__typename": "Movie",
				"title": "Gone With the Wind",
				"releaseDate": "2020-11-5",
			},
			{
				"__typename": "Genre",
				"name": "Classic",
				"description": "Example genre description"
			}
		]
	}
}