Adding Post Meta from Frontend wpgraphql in WordPress

Adding and Managing Post Meta via WPGraphQL in WordPress Frontend

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
}
PHP

Metabox 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']));
        }
     
    }
    
    
}
PHP

Registering 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);
          },
      ));
    }

}
PHP

Updating 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;
    }


}
PHP

GraphQL 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']);
      }
    }



}
PHP

This 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']);
      }
    }
    
    
}
PHP

With 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!