Master of the universe

WPGraphQL is a powerful and flexible tool that allows developers to interact with Wordpress data using GraphQL. It provides an efficient way to fetch or modify data, enabling you to build modern and performant applications. In this article, we will delve into customizing the WPGraphQL schema to extend its capabilities and tailor it to your specific needs.

Introduction

WPGraphQL exposes Wordpress data using a GraphQL schema, which defines the types, connections, and mutations available for querying and modifying data. By customizing the schema, you can add, modify, or remove fields, connections, and types to better suit your project requirements.

Setting Up Your Environment

Before we dive into customizing the WPGraphQL schema, let's set up the necessary environment.

Installing WPGraphQL plugin

To use WPGraphQL, you'll first need to install the plugin. You can download it from the official Wordpress plugin repository or install it via the Wordpress admin dashboard.

Creating a custom plugin for schema customization

To keep your schema customizations organized and separate from the core WPGraphQL plugin, it's best to create a custom plugin. This custom plugin will contain all your schema modifications. Follow the official Wordpress guide to create a custom plugin.

Customizing Types

Types are the building blocks of the GraphQL schema. Customizing types allows you to add, modify, or remove fields to better represent your data.

Adding Custom Fields

To add a custom field to an existing type, you can use the register_graphql_field function. Here's an example of adding a custom field wordCount to the Post type:

php
add_action('graphql_register_types', function () {
    register_graphql_field('Post', 'wordCount', [
        'type' => 'Int',
        'description' => 'The word count of the post content.',
        'resolve' => function ($post) {
            $content = get_post_field('post_content', $post->ID);
            $word_count = str_word_count(strip_tags($content));
            return $word_count;
        },
    ]);
});

Removing Fields from Types

To remove an unnecessary field from an existing type, you can use the deregister_graphql_field function. Here's an example of removing the date field from the User type:

php
add_action('graphql_register_types', function () {
    deregister_graphql_field('User', 'date');
});

Customizing Connections

Connections are the relationships between types in the schema. Customizing connections allows you to create new connections or modify existing ones.

https://www.youtube.com/watch?v=r2U-LlRAgcU

Adding Custom Connections

To create a custom connection between two types, use the register_graphql_connection function. Here's an example of connecting a custom post type event to a custom taxonomy event_category:

php
add_action('graphql_register_types', function () {
    register_graphql_connection([
        'fromType' => 'Event',
        'toType' => 'EventCategory',
        'fromFieldName' => 'eventCategories',
        'connectionArgs' => [],
        'resolve' => function ($source, $args, $context, $info) {
            $categories = get_the_terms($source->ID, 'event_category');
            return !empty($categories) ? $categories : [];
        },
    ]);
});

Modifying Connection Arguments

To customize the arguments for an existing connection, you can use the graphql_connection_args filter. Here's an example of adding a custom filter argument hasThumbnail to the posts connection:

php
add_filter('graphql_connection_args', function ($args, $source, $field_key, $field) {
if ($field_key === 'posts') {
$args['hasThumbnail'] = [
'type' => 'Boolean',
'description' => 'Filter posts that have a featured image',
];
}
return $args;
}, 10, 4);

add_filter('graphql_post_object_connection_query_args', function ($query_args, $source, $args) {
if (isset($args['hasThumbnail'])) {
$meta_query = [
'key' => '_thumbnail_id',
'compare' => $args['hasThumbnail'] ? 'EXISTS' : 'NOT EXISTS',
];
$query_args['meta_query'][] = $meta_query;
}
return $query_args;
}, 10, 3);

Customizing Enumerations

Enumerations, or enums, are a special type of scalar that represents a finite set of values. Customizing enums allows you to modify or add new enum values.

Modifying Enum Values or Adding Custom Enums

To modify enum values or add custom enums, you can use the register_graphql_enum_type function. Here's an example of adding a custom post status archived to the PostStatusEnum:

php
add_action('graphql_register_types', function () {
    register_graphql_enum_type('PostStatusEnum', [
        'values' => [
            'ARCHIVED' => [
                'value' => 'archived',
                'description' => 'An archived post status',
            ],
        ],
    ]);
});

Customizing Input Types

Input types define the shape of input data for mutations. Customizing input types allows you to add or modify fields for creating or updating data.

Adding a Custom Field to the CreatePostInput Type

To add a custom field to an input type, you can use the register_graphql_input_field function. Here's an example of adding a custom field isFeatured to the CreatePostInput type:

php
add_action('graphql_register_types', function () {
    register_graphql_input_field('CreatePostInput', 'isFeatured', [
        'type' => 'Boolean',
        'description' => 'Whether the post should be marked as featured',
    ]);
});

Adding Custom Types

To create entirely new types in the schema, you can use the register_graphql_object_type function. Here's an example of adding a custom post type testimonial to the schema:

php
add_action('graphql_register_types', function () {
    register_graphql_object_type('Testimonial', [
        'description' => 'A testimonial post type',
        'fields' => [
            'id' => [
                'type' => 'ID',
                'description' => 'Unique identifier for the testimonial',
            ],
            'title' => [
                'type' => 'String',
                'description' => 'The title of the testimonial',
            ],
            'content' => [
                'type' => 'String',
                'description' => 'The content of the testimonial',
            ],
        ],
    ]);
});

Registering Custom Scalars

Scalars are the primitive data types in the schema. You can register custom scalar types using the register_graphql_scalar function. Here's an example of registering a custom date scalar:

php
add_action('graphql_register_types', function () {
    register_graphql_scalar('CustomDate', [
        'serialize' => function ($value) {
            return date('Y-m-d', strtotime($value));
        },
        'parseValue' => function ($value) {
				return date('Y-m-d', strtotime($value));
    },
    'parseLiteral' => function ($ast) {
        if ($ast->kind !== 'StringValue') {
            return null;
        }
        return date('Y-m-d', strtotime($ast->value));
    },
    'description' => 'A custom date scalar in the format Y-m-d',
]);

Customizing Resolvers

Resolvers are responsible for fetching or modifying data in response to a query or mutation. Customizing resolvers allows you to modify default resolvers or add custom resolvers for your new fields.

Customizing the Resolver for a Custom Field

To customize the resolver for a custom field, you can define a resolve function when registering the field. Here's an example of customizing the resolver for a custom field rating on the Post type:

add_action('graphql_register_types', function () {
    register_graphql_field('Post', 'rating', [
        'type' => 'Int',
        'description' => 'The average rating of the post',
        'resolve' => function ($post) {
            $ratings = get_post_meta($post->ID, 'ratings', true);
            $average_rating = !empty($ratings) ? array_sum($ratings) / count($ratings) : 0;
            return round($average_rating);
        },
    ]);
});

Best Practices for Customizing the Schema

Following best practices when customizing the WPGraphQL schema will help you maintain a clean and consistent codebase:

  • Follow naming conventions: Adhere to the naming conventions used in the WPGraphQL schema to keep your customizations consistent and easy to understand.
  • Structure your custom plugin: Organize your custom plugin by splitting your customizations into separate files based on their purpose (e.g., types, fields, connections, etc.).
  • Cache considerations: Be mindful of performance implications and caching strategies when customizing the schema. Consider using the WPGraphQL cache helpers to cache your custom resolvers.

Conclusion

Customizing the WPGraphQL schema offers endless possibilities for tailoring your Wordpress data and API to meet your project requirements. By following the examples and best practices outlined in this article, you'll be well on your way to building a powerful and flexible API using WPGraphQL.

Frequently Asked Questions

Can I modify the default behavior of an existing field without removing it?

Yes, you can modify the default behavior of an existing field by using the graphql_register_types action to override the resolver function. For example, if you want to modify the title field of the Post type to always return an uppercase string, you can do the following:

php
add_action('graphql_register_types', function () {
    register_graphql_field('Post', 'title', [
        'type' => 'String',
        'description' => 'The title of the post',
        'resolve' => function ($post) {
            $title = get_post_field('post_title', $post->ID);
            return strtoupper($title);
        },
    ]);
});

How can I add custom mutations to the WPGraphQL schema?

To add custom mutations, you can use the register_graphql_mutation function. Here's an example of registering a custom mutation to increment a post's view count:

php
add_action('graphql_register_types', function () {
    register_graphql_mutation('incrementPostViews', [
        'inputFields' => [
            'postId' => [
                'type' => 'ID',
                'description' => 'The ID of the post to increment views',
            ],
        ],
        'outputFields' => [
            'post' => [
                'type' => 'Post',
                'description' => 'The updated post object',
                'resolve' => function ($payload) {
                    return get_post(absint($payload['postId']));
                },
            ],
        ],
        'mutateAndGetPayload' => function ($input) {
            $post_id = absint($input['postId']);
            $current_views = get_post_meta($post_id, 'views', true);
            $updated_views = $current_views + 1;
            update_post_meta($post_id, 'views', $updated_views);
            return ['postId' => $post_id];
        },
    ]);
});

Can I add custom directives to the WPGraphQL schema?

As of now, WPGraphQL does not support custom directives out of the box. However, you can follow the discussion on this topic in the official WPGraphQL GitHub repository for updates and potential workarounds.

How do I expose custom taxonomies and custom post types in WPGraphQL?

WPGraphQL automatically exposes custom taxonomies and custom post types as long as they have the show_in_graphql property set to true when registering them. Make sure to also provide the graphql_single_name and graphql_plural_name properties. For example:

php
register_post_type('event', [
    'show_in_graphql' => true,
    'graphql_single_name' => 'Event',
    'graphql_plural_name' => 'Events',
    // ... other properties
]);

register_taxonomy('event_category', 'event', [
    'show_in_graphql' => true,
    'graphql_single_name' => 'EventCategory',
    'graphql_plural_name' => 'EventCategories',
    // ... other properties
]);

How do I secure my WPGraphQL schema by limiting access to specific fields, types, or connections?

You can use the graphql_authorize filter to control access to specific fields, types, or connections in your schema. This filter allows you to define conditions that must be met for a user to access certain parts of the schema. For example, you can limit access to the email field of the User type to only users with the `

Sign up for the Artisan Beta

Help us reimagine WordPress.

Whether you’re a smaller site seeking to optimize performance, or mid-market/enterprise buildinging out a secure WordPress architecture – we’ve got you covered. 

We care about the protection of your data. Read our Privacy Policy.