WordPress provides a powerful GraphQL API through the WPGraphQL plugin, allowing developers to interact with the content management system in a more flexible and efficient manner. In this tutorial, we’ll explore how to add and update post meta (custom fields) from the frontend using GraphQL.
Setting Up the Environment
Before we dive into the code, make sure you have the WPGraphQL plugin installed and activated on your WordPress site. Additionally, create a class to handle the GraphQL functionalities. For this example, let’s name it CustomGraphQL
.
class CustomGraphQL {
// your code goes here
}
PHPMetabox in the Backend
Now, create a metabox in the backend to capture the ‘dishName’ input. This is beyond the scope of this tutorial, but you can use the add_meta_box
function to achieve this.
class CustomGraphQL {
private $_post_type = 'dish';
public function __construct()
{
add_action('init', array($this, 'register_post_type'));
add_action('add_meta_boxes', array($this, 'add_meta_boxes'));
add_action('save_post', array($this, 'save_meta_box_data'));
}
// Register the custom post type
public function register_post_type()
{
$labels = array(
'name' => _x('Dishes', 'post type general name', 'menu-crafter'),
'singular_name' => _x('Dish', 'post type singular name', 'menu-crafter'),
'menu_name' => _x('Dishes', 'admin menu', 'menu-crafter'),
'name_admin_bar' => _x('Dish', 'add new on admin bar', 'menu-crafter'),
'add_new' => _x('Add New', 'dish', 'menu-crafter'),
'add_new_item' => __('Add New Dish', 'menu-crafter'),
'new_item' => __('New Dish', 'menu-crafter'),
'edit_item' => __('Edit Dish', 'menu-crafter'),
'view_item' => __('View Dish', 'menu-crafter'),
'all_items' => __('All Dishes', 'menu-crafter'),
'search_items' => __('Search Dishes', 'menu-crafter'),
'parent_item_colon' => __('Parent Dishes:', 'menu-crafter'),
'not_found' => __('No dishes found.', 'menu-crafter'),
'not_found_in_trash' => __('No dishes found in Trash.', 'menu-crafter'),
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'dish'),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => null,
'supports' => array('title'),
// Add support for GraphQL.
'show_in_graphql' => true,
'graphql_single_name' => 'dish',
'graphql_plural_name' => 'dishes',
'graphql_exclude_mutations' => [
'create',
'update',
'delete'
],
);
register_post_type($this->_post_type, $args);
}
// Add meta box for the custom post type
public function add_meta_boxes()
{
add_meta_box(
'dish_meta_box', // Unique ID
'Dish Information', // Box title
array($this, 'display_meta_box'), // Callback function to display the meta box
$this->_post_type, // Post type
'normal', // Context
'high' // Priority
);
}
// Display the meta box content
public function display_meta_box($post)
{
// Retrieve existing values from the database
$dish_name = get_post_meta($post->ID, '_dish_name', true);
// HTML for the form ?>
<label for="dish_name">Dish Name:</label>
<input type="text" id="dish_name" name="_dish_name" value="<?php echo esc_attr($dish_name); ?>" style="width: 100%;" />
<?php
}
// Save meta box data
public function save_meta_box_data($post_id)
{
// Check if autosave
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// Check if the user has permissions to save data
if (!current_user_can('edit_post', $post_id)) {
return;
}
// Save meta box data
if (isset($_POST['_dish_name'])) {
update_post_meta($post_id, '_dish_name', sanitize_text_field($_POST['_dish_name']));
}
}
}
PHPRegistering GraphQL Fields
Before you start you have to make sure that your post type is exposed to graphql. Now, start by registering GraphQL fields for your custom post type. In this example, we’ll use a custom post type called ‘Dish’ and a custom meta field ‘_dish_name’. Add the following code to your CustomGraphQL
class.
This code registers a ‘dishName’ field for the ‘Dish’ type, fetching the corresponding post meta value.
class CustomGraphQL {
public function __construct()
{
// previous code
add_action('graphql_register_types', array($this, 'register_graphql_fields'));
}
// previous code
public function register_graphql_fields() {
// Register GraphQL fields for the 'Dish' type
register_graphql_field('Dish', 'dishName', array(
'type' => 'String',
'resolve' => function ($post) {
return get_post_meta($post->ID, '_dish_name', true);
},
));
}
}
PHPUpdating GraphQL Input Fields
To reflect the changes in the GraphQL input fields, modify the ‘UpdateDishInput’ and ‘CreateDishPayload’. Add the following code to your CustomGraphQL
class.
class CustomGraphQL {
public function __construct()
{
// previous code
add_action('graphql_register_types', array($this, 'register_graphql_fields'));
add_filter('graphql_input_fields', array($this, 'graphql_register_edit_mutation'), 10, 2);
}
// previous code
public function register_graphql_fields() {
// Register GraphQL fields for the 'Dish' type
register_graphql_field('Dish', 'dishName', array(
'type' => 'String',
'resolve' => function ($post) {
return get_post_meta($post->ID, '_dish_name', true);
},
));
}
public function graphql_register_edit_mutation($input_fields, $type_name) {
if ($type_name === "UpdateDishInput" || $type_name === "CreateDishPayload") {
$input_fields['dishName'] = [
'type' => 'String',
'description' => __('A string containing the dish name.', 'wp-graphql'),
];
}
return $input_fields;
}
}
PHPGraphQL Mutation for Updating Meta
Now, let’s handle the GraphQL mutation to update the custom meta field. Add the following code to your CustomGraphQL
class.
class CustomGraphQL {
public function __construct()
{
// previous code
add_action('graphql_register_types', array($this, 'register_graphql_fields'));
add_filter('graphql_input_fields', array($this, 'graphql_register_edit_mutation'), 10, 2);
add_action('graphql_post_object_mutation_update_additional_data', array($this, 'graphql_register_edit_mutation_meta_data'), 10, 5);
}
// previous code
public function register_graphql_fields() {
// Register GraphQL fields for the 'Dish' type
register_graphql_field('Dish', 'dishName', array(
'type' => 'String',
'resolve' => function ($post) {
return get_post_meta($post->ID, '_dish_name', true);
},
));
}
public function graphql_register_edit_mutation($input_fields, $type_name) {
if ($type_name === "UpdateDishInput" || $type_name === "CreateDishInput") {
$input_fields['dishName'] = [
'type' => 'String',
'description' => __('A string containing the dish name.', 'wp-graphql'),
];
}
return $input_fields;
}
public function graphql_register_edit_mutation_meta_data($post_id, $input, $mutation_name, $context, $info) {
if (!empty($input['dishName'])) {
update_post_meta($post_id, '_dish_name', $input['dishName']);
}
}
}
PHPThis code checks if the ‘dishName’ input is provided and updates the ‘_dish_name’ post meta accordingly.
Here is the complete class.
class CustomGraphQL {
private $_post_type = 'dish';
public function __construct()
{
add_action('init', array($this, 'register_post_type'));
add_action('add_meta_boxes', array($this, 'add_meta_boxes'));
add_action('save_post', array($this, 'save_meta_box_data'));
// graphql edits
add_action('graphql_register_types', array($this, 'register_graphql_fields'));
add_filter('graphql_input_fields', array($this, 'graphql_register_edit_mutation'), 10, 2);
add_action('graphql_post_object_mutation_update_additional_data', array($this, 'graphql_register_edit_mutation_meta_data'), 10, 5);
}
// Register the custom post type
public function register_post_type()
{
$labels = array(
'name' => _x('Dishes', 'post type general name', 'menu-crafter'),
'singular_name' => _x('Dish', 'post type singular name', 'menu-crafter'),
'menu_name' => _x('Dishes', 'admin menu', 'menu-crafter'),
'name_admin_bar' => _x('Dish', 'add new on admin bar', 'menu-crafter'),
'add_new' => _x('Add New', 'dish', 'menu-crafter'),
'add_new_item' => __('Add New Dish', 'menu-crafter'),
'new_item' => __('New Dish', 'menu-crafter'),
'edit_item' => __('Edit Dish', 'menu-crafter'),
'view_item' => __('View Dish', 'menu-crafter'),
'all_items' => __('All Dishes', 'menu-crafter'),
'search_items' => __('Search Dishes', 'menu-crafter'),
'parent_item_colon' => __('Parent Dishes:', 'menu-crafter'),
'not_found' => __('No dishes found.', 'menu-crafter'),
'not_found_in_trash' => __('No dishes found in Trash.', 'menu-crafter'),
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array('slug' => 'dish'),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => null,
'supports' => array('title'),
// Add support for GraphQL.
'show_in_graphql' => true,
'graphql_single_name' => 'dish',
'graphql_plural_name' => 'dishes',
'graphql_exclude_mutations' => [
'create',
'update',
'delete'
],
);
register_post_type($this->_post_type, $args);
}
// Add meta box for the custom post type
public function add_meta_boxes()
{
add_meta_box(
'dish_meta_box', // Unique ID
'Dish Information', // Box title
array($this, 'display_meta_box'), // Callback function to display the meta box
$this->_post_type, // Post type
'normal', // Context
'high' // Priority
);
}
// Display the meta box content
public function display_meta_box($post)
{
// Retrieve existing values from the database
$dish_name = get_post_meta($post->ID, '_dish_name', true);
// HTML for the form ?>
<label for="dish_name">Dish Name:</label>
<input type="text" id="dish_name" name="_dish_name" value="<?php echo esc_attr($dish_name); ?>" style="width: 100%;" />
<?php
}
// Save meta box data
public function save_meta_box_data($post_id)
{
// Check if autosave
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// Check if the user has permissions to save data
if (!current_user_can('edit_post', $post_id)) {
return;
}
// Save meta box data
if (isset($_POST['_dish_name'])) {
update_post_meta($post_id, '_dish_name', sanitize_text_field($_POST['_dish_name']));
}
}
// previous code
public function register_graphql_fields() {
// Register GraphQL fields for the 'Dish' type
register_graphql_field('Dish', 'dishName', array(
'type' => 'String',
'resolve' => function ($post) {
return get_post_meta($post->ID, '_dish_name', true);
},
));
}
public function graphql_register_edit_mutation($input_fields, $type_name) {
if ($type_name === "UpdateDishInput" || $type_name === "CreateDishInput") {
$input_fields['dishName'] = [
'type' => 'String',
'description' => __('A string containing the dish name.', 'wp-graphql'),
];
}
return $input_fields;
}
public function graphql_register_edit_mutation_meta_data($post_id, $input, $mutation_name, $context, $info) {
if (!empty($input['dishName'])) {
update_post_meta($post_id, '_dish_name', $input['dishName']);
}
}
}
PHPWith these steps, you’ve successfully set up the GraphQL integration for adding and updating custom post meta from the frontend in WordPress. Make sure to adapt the code according to your specific use case and requirements.
Happy coding!