Comments (2)
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.
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)
- SendPasswordResetEmail Doesn't Display Reset Link in Received Emails Due to Formatting Issue with <> characters HOT 3
- Unable to query menuItems from "UTILITY" menu location with Apollo (works in GraphiQL) HOT 5
- Sticky posts are ignored HOT 3
- incompatible with custom field for oder by (mysql aggregated reason) HOT 2
- PHP deprecated HOT 6
- mediaDetails sizes query returns incorrect value for "file" HOT 4
- Test against WordPress 6.4
- tests: GraphiQL e2e tests failing on WordPress 6.4
- Fatal error in `WPConnectionType` when calling `str_ends_with()` on PHP < 8.0 HOT 7
- Query failing when a linked post type has a draft HOT 4
- Querying parent info in preview mode returns the current post info. HOT 3
- Add workflow to help automate version numbers during releases HOT 2
- No error thrown when query value first exceeds max query amount HOT 8
- nodeByUri return null for some custom CPT HOT 3
- Let's Revamp Our IDE 🚀 HOT 1
- Document Previews in WPGraphQL
- Return GRAPHQL_DEBUG message when meta query is used in a GraphQL Request HOT 7
- Menu returning wrong items HOT 1
- Post Author Name node repeats when fetching multiple posts at once HOT 3
- Unhelpful error when a non-existing type is referenced as a Field's type
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wp-graphql.