Coder Social home page Coder Social logo

Comments (2)

jasonbahl avatar jasonbahl commented on May 27, 2024

So, new Types can already be registered and queries can be registered to resolve those types.

Here's an example PR to the Bylines plugin: https://github.com/danielbachhuber/bylines/pull/48/files

While that PR didn't get merged to the Bylines plugin, it serves as an example of how new Types can easily be registered to WPGraphQL.

I'll walk through how to do it:

First, we only need to execute our code if the GraphQL plugin is enabled, so we can hook into graphql_init to bootstrap the functionality we need.

In Bylines case, we do: add_action( 'graphql_init', array( 'Bylines\Integrations\GraphQL\GraphQL', 'init' ) );

This instantiates the GraphQL integration class. Let's look at what's happening there.

public static function init() {
     add_action( 'do_graphql_request', array(
          'Bylines\Integrations\GraphQL\GraphQL',
          'filter_post_object_fields',
     ) );
     add_filter( 'graphql_default_query_args', array(
          'Bylines\Integrations\GraphQL\GraphQL',
          'filter_byline_post_object_query_args',
     ), 10, 5 );
     add_filter( 'graphql_resolve_node', array(
          'Bylines\Integrations\GraphQL\GraphQL',
          'filter_resolve_node',
     ), 10, 3 );
     add_filter( 'graphql_resolve_node_type', array(
          'Bylines\Integrations\GraphQL\GraphQL',
          'filter_resolve_node_type',
     ), 10, 2 );
}

Here' we hook into 1 action and 3 filters. Let's see what this does.

The first thing we do is hook into the do_graphql_request action, (which only fires if WordPress is processing a GraphQL request), and we set our callback to filter_post_object_fields

In this callback, we get the supported/allowed post_types from both the Bylines plugin and WPGraphQL.

Then, we loop through the Bylines supported post_type's, ensure they're also WPGraphQL supported, and if so, we add a filter to their fields (the GraphQL Schema for that post_type)

The callback for that filter is post_object_fields which receives an array of the $fields already defined for that type, and expects $fields to be returned.

We modify that array and add a bylines field.

Here, we define the Type, Description and Resolve method:

$fields['bylines'] = [
	'type'        => Types::list_of( self::byline_type() ),
	'description' => __( 'The bylines for the object', 'bylines' ),
	'resolve'     => function( \WP_Post $post, array $args, AppContext $context, ResolveInfo $info ) {
		$bylines = get_bylines( $post );

		return ! empty( $bylines ) ? $bylines : null;
	},
];

We define the type to return a list of Bylines (the byline_type). This means that when querying a post, if we query for bylines the consumer should expect an array of objects that adhere to the schema defined for the byline_type (we'll look at that in a sec).

Then we add a quick description (translated, of course).

Then, we set our resolve function. The resolver gets the parent object passed down to it, as well as field $args, AppContext, and ResolveInfo.

In this case we're just concerned with the parent object, which would be the Post object.

We take that post, and we query for bylines of that post, and we return the response.

The response we're returning here is an array, and each object will pass it's info to the Byline type, where the fields defined on the Byline type will be responsible for resolving to something more concrete.

So, let's take a look at the Byline type definition (https://github.com/danielbachhuber/bylines/pull/48/files#diff-70582024319fc161d0abb5ee938cc14f)

The gist of this class is that we create a new class BylineType which extends WPObjectType and in here we give the type a name, description, fields, and implement the node_interface

The fields are what resolve to concrete data.

So, when a user queries for bylines on a post, we run get_bylines( $post ) on that Post, and return the results of that to our iterator, which then passes to the BylineType to resolve.

Here, each field gets passed the Byline that was retrieved from get_bylines() and returns something. In our case, we're simply returning scalar values (and a global ID).

'displayName' => [
	'type' => Types::string(),
	'description' => __( 'The display name of the byline', 'bylines' ),
	'resolve' => function( Byline $byline, $args, AppContext $context, ResolveInfo $info ) {
		$name = $byline->display_name;
		return ! empty( $name ) ? esc_html( $name ) : null;
	},
],

Then, we also add connections to all the post_types that the Byline type is connected with, to make our queries truly Graph-like.

foreach ( $byline_post_types as $post_type ) {
	if ( in_array( $post_type, $graphql_post_types, true ) ) :
		$post_type_object = get_post_type_object( $post_type );
		$fields[ $post_type_object->graphql_plural_name ] = PostObjectConnectionDefinition::connection( $post_type_object );
	endif;
}

Pretty simple so far, eh?

We've got a Byline Type registered, and we've filtered the posts fields to add a bylines field to each postType that is supported by both GraphQL and the Bylines plugin.

Now, it's possible that posts can be queried as a field of a byline, so we only want posts connected to that Byline to be queried for, we don't want just random posts. . .so we need to adjust our WP_Query $args to only query for posts connected to the currently resolving Byline.

So, our next filter was:

add_filter( 'graphql_default_query_args', array(
	'Bylines\Integrations\GraphQL\GraphQL',
	'filter_byline_post_object_query_args',
), 10, 5 );

And the callback looks like:

if ( true === is_object( $source ) ) {
	switch ( true ) {
		case $source instanceof Byline:
			$query_args['tax_query'] = array(
				array(
					'taxonomy' => 'byline',
					'terms'    => [ $source->term_id ],
					'field'    => 'term_id',
				),
			);
			break;
		default:
			break;
	}
}

/**
 * Return the $query_args
 */
return $query_args;

Here, we check if the $source of the field we're resolving is a Byline, we should adjust the query_args to include a tax_query for just the Byline that we're currently resolving.

Pretty neat!

Now, the only thing left is to flesh out support for the Byline type being a "node"

So, let's look at the other 2 filters we added:

add_filter( 'graphql_resolve_node', array(
	'Bylines\Integrations\GraphQL\GraphQL',
	'filter_resolve_node',
), 10, 3 );
add_filter( 'graphql_resolve_node_type', array(
	'Bylines\Integrations\GraphQL\GraphQL',
	'filter_resolve_node_type',
), 10, 2 );

These filters hook into the mechanisms that allow node queries to be resolved.

If you look at the callbacks, they're pretty simple. In one case, we show how to resolve the node ( Byline::get_by_term_id() ), and in the other one we simply return the Byline Type definition if the resolving node is a Byline.

So now we can run a node query, using the ID of a Byline and properly have a Byline resolve!

from wp-graphql.

jasonbahl avatar jasonbahl commented on May 27, 2024

Closing this as there is no "issue" and it's been documented how to do it here in the above comments, and here: #173

from wp-graphql.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.