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"
}
]
}
}