Tag: Custom Fields

  • Deprecating a field in the Schema

    Sometimes it can be helpful to deprecate a field in the Schema without removing it altogether.

    This snippet shows how to deprecate the `Post.excerpt` field.

    You can use this technique to deprecate other fields.

    // Filter the Object Fields
    add_filter( 'graphql_object_fields', function( $fields, $type_name, $wp_object_type, $type_registry ) {
    
            // If the Object Type is not the "Post" Type
            // return the fields unaltered
    	if ( 'Post' !== $type_name ) {
    		return $fields;
    	}
    
            // If the excerpt field doesn't exist 
            // (removed by another plugin, for example)
            // return the fields unaltered
    	if ( ! isset( $fields['excerpt'] ) ) {
    		return  $fields;
    	}
    
            // Add a deprecation reason to the excerpt field
    	$fields['excerpt']['deprecationReason'] = __( 'Just showing how to deprecate an existing field', 'your-textdomain' );
    	
            // return the modified
            return $fields;
    
    }, 10, 4 );

    After using this snippet, we can verify in the WPGraphQL Schema Docs that the field is indeed deprecated:

    Screenshot of the excerpt field showing deprecated in the GraphiQL IDE Schema Docs
  • Register a basic Mutation

    This snippet shows how to register a basic GraphQL Mutation with a single input field, a single output field, and the input is simply returned as the value for the output.

    add_action( 'graphql_register_types', function() {
    
    	register_graphql_mutation( 'testMutation', [
    		'inputFields' => [
    			'phoneNumber' => [
    				'type' => [ 'non_null' => 'String' ],
    			],
    		],
    		'outputFields' => [
    			'phoneNumber' => [
    				'type' => 'String',
    			],
    		],
    		'mutateAndGetPayload' => function( $input ) {
    
    			return [
    				'phoneNumber' => $input['phoneNumber'] ?? null,
    			];
    
    		}
    	]);
    
    } );
  • Add Edit Link to All Post Types

    The following snippet shows how to add the “Edit” link as a GraphQL field to all post types:

    add_action( 'graphql_register_types', function() {
    
    	register_graphql_field( 'ContentNode', 'editLink', [
    		'type' => 'String',
    		'description' => __( 'Link to edit the content', 'your-textdomain' ),
    		'resolve' => function( \WPGraphQL\Model\Post $post, $args, $context, $info ) {
    		   return get_edit_post_link( $post->databaseId );
    		}
    	]);
    
    } );

    This could then be queried like so:

    Screenshot of a GraphQL Query for posts with their editLink
    Screenshot of a GraphQL Query for posts with their editLink
  • Add field to output URLs for Sitemap

    The following code is an example of how you can create a field called allUrls that will output site URLs that could be used to generate a sitemap.

    The resolver uses mostly hard-coded data, but shows what a potential solution could look like.

    add_action( 'graphql_register_types', function() {
    
    	register_graphql_field( 'RootQuery', 'allUrls', [
    		'type' => [ 'list_of' => 'String' ],
    		'description' => __( 'A list of all urls. Helpful for rendering sitemaps', 'your-textdomain' ),
    		'resolve' => function() {
    
    			// Start collecting all URLS
    			$meta_urls = array( get_home_url() );
    
                            // Hardcoded array. You would need to fetch the URLs for all Posts
    			$all_posts = [ 'site.com/post', 'site.com/post-2' ];
    
                            // Hardcoded array. You would need to fetch the URLs for all Terms
    			$all_terms = [ 'site.com/tag', 'site.com/category' ];
    
    			return array_merge($meta_urls, $all_posts, $all_terms);
    
    		}
    	]  );
    
    });

    You can then query this field using:

    {
      allUrls
    }
    Querying the allUrls field in GraphiQL
  • Register GraphQL Field with Argument

    This is an example of registering a field with an argument showing how to use the argument in a resolver.

    add_action( 'graphql_register_types', function() {
    
    	register_graphql_field( 'RootQuery', 'myNewField', [
    		'type' => 'String',
    		'args' => [
    			'myArg' => [
    				'type' => 'String',
                                    'description' => __( 'Description for how the argument will impact the field resolver', 'your-textdomain' ),
    			],
    		],
    		'resolve' => function( $source, $args, $context, $info ) {
    			if ( isset( $args['myArg'] ) ) {
    				return 'The value of myArg is: ' . $args['myArg'];
    			}
    			return 'test';
    		},
    	]);
    
    });

    This will register a new field (myNewField ) to the RootQuery, and adds an argument to the field (myArg). The resolve function checks to see if that arg is set, and if so, it returns the value, if not it returns test.

    We can query this like so:

    query {
      myNewField
    }

    And the results will be:

    {
      "data": {
        "myNewField": "test"
      }
    }

    Now, we can pass a value to the argument like so:

    query {
      myNewField( myArg: "something" )
    }

    and the results will be:

    {
      "data": {
        "myNewField": "The value of myArg is: something"
      }
    }

    Now, you can introduce variables like so:

    query MyQuery($myArg:String) {
      myNewField( myArg: $myArg )
    }

    And then you can pass variables to the request. Here’s an example of using a variable in GraphiQL:

    Custom field with an argument and variable in GraphiQL
  • Register field as a list of strings

    The below code registers a field called listOfStrings that returns a list of strings as the result:

    add_action( 'graphql_register_types', function() {
    
    	register_graphql_field( 'RootQuery', 'listOfStrings', [
    		'type' => [ 'list_of' => 'String' ],
    		'resolve' => function() {
    			return [
    				'String One',
    				'String Two'
    			];
    		}
    	] );
    
    } );

    This field can now be queried:

    {
      listOfStrings
    }
    ListOfStrings field results displayed in GraphiQL
  • Register object and field for custom list of users

    The following code creates an object type called StuntPerformer and creates a field on the RootQuery called stuntPerformers that returns a custom list of users.

    In this case, the list of users are the admins of the website, but custom logic could be added to return a curated list of users.

    add_action( 'graphql_register_types', function() {
    
    	register_graphql_object_type(
    		'StuntPerformer',
    		[
    			'description' => __( 'Stunt Performer', 'bsr' ),
    			'fields'      => [
    				'firstName' => [
    					'type'        => 'String',
    					'description' => 'first name'
    				],
    				'lastName'  => [
    					'type'        => 'String',
    					'description' => 'last name'
    				],
    				'uid'       => [
    					'type'        => 'String',
    					'description' => 'user id'
    				]
    			],
    		]
    	);
    
    	register_graphql_field(
    		'RootQuery',
    		'stuntPerformers',
    		[
    			'description' => __( 'Return stunt performers', 'bsr' ),
    			'type'        => [ 'list_of' => 'stuntPerformer' ],
    			'resolve'     => function() {
    				$stunt_performers = [];
    				$performers       = get_users( array(
    					'role__in' => 'administrator'
    				) );
    
    				foreach ( $performers as $p ) {
    					$performer = [
    						'firstName' => $p->first_name,
    						'lastName'  => $p->last_name,
    						'uid'       => $p->ID
    					];
    
    					$stunt_performers[] = $performer;
    				}
    
    				return $stunt_performers;
    			}
    		]
    	);
    
    } );

    You can now query for these stuntPerformers with the following GraphQL:

    {
      stuntPerformers {
        firstName
        lastName
        uid
      } 
    }
    Stunt Performers query in GraphiQL
  • List of Key Values

    This is an example showing how to return a list of keys and values where the keys and values are both strings.

    add_action( 'graphql_register_types', function() {
    
    	register_graphql_object_type( 'keyValue', [
    		'description' => __( 'Keys and their values, both cast as strings', 'your-textdomain' ),
    		'fields'      => [
    			'key'   => [
    				'type' => 'String',
    			],
    			'value' => [
    				'type' => 'String',
    			],
    		]
    	] );
    
    	register_graphql_field( 'RootQuery', 'listOfKeyValues', [
    		'type'        => [ 'list_of' => 'KeyValue' ],
    		'description' => __( 'Field that resolves as a list of keys and values', 'your-textdomain' ),
    		'resolve'     => function() {
    			$mock_array = [
    				'key1' => 'Value1',
    				'key2' => 'Value2',
    				'key3' => 'Value3'
    			];
    
    			$list = [];
    			foreach ( $mock_array as $key => $value ) {
    				$list[] = [
    					'key' => $key,
    					'value' => $value,
    				];
    			}
    
    			return $list;
    		}
    	] );
    
    } );
  • Add Primary Category field for The SEO Framework plugin

    The following adds a field called primaryCat field when using The SEO Framework WordPress Plugin

    add_action( 'init', function() {
    
    	register_graphql_connection([
    		'fromType' => 'Post',
    		'toType' => 'Category',
    		'fromFieldName' => 'primaryCat',
    		'oneToOne' => true,
    		'resolve' => function( \WPGraphQL\Model\Post $post, $args, $context, $info ) {
    
    			$primary_term = null;
    
    			if ( function_exists( 'the_seo_framework' ) ) {
    				$primary_term = the_seo_framework()->get_primary_term( $post->ID, 'category' );
    			}
    
    			// If there's no primary term from the SEO Framework, get the first category assigned
    			if ( empty( $primary_term ) ) {
    				$terms = get_the_terms( $post->ID, 'category' );
    				if ( ! empty( $terms ) ) {
    					$primary_term = $terms[0]->term_id;
    				}
    			}
    
    			// If there's no primary term, return null for the connection
    			if ( empty( $primary_term ) ) {
    				return null;
    			}
    
    			$resolver = new \WPGraphQL\Data\Connection\TermObjectConnectionResolver( $post, $args, $context, $info, 'category' );
    			$resolver->set_query_arg( 'include', absint( $primary_term ) );
    			return $resolver->one_to_one()->get_connection();
    
    		}
    	]);
    
    } );
  • Add field for unencoded content

    The following adds a field to the NodeWithContentEditor interface to get the unencoded content for a post:

    add_action( 'graphql_register_types', function() {
    	register_graphql_field( 'NodeWithContentEditor', 'unencodedContent', [
    		'type' => 'String',
    		'resolve' => function( $post ) {
    			$content = get_post( $post->databaseId )->post_content;
    			return ! empty( $content ) ?  apply_filters( 'the_content', $content ) : null;
    		}
    	]);
    });

    You can query now query for this field:

    {
      contentNode(id: 952, idType: DATABASE_ID) {
        id
        ... on NodeWithTitle {
          title
        }
        ... on NodeWithContentEditor {
          content
          unencodedContent
        }
      }
    }
    Unencoded Content query in GraphiQL

    Related Links