Adding meta boxes to a custom post type in WordPress

Adding meta boxes to a custom post type in WordPress

Online by JSC0d3
August 12, 2017 | | | | | 2764 recognitions

We know that WordPress developers struggle to create meta boxes with custom fields. We know the Codex does not have enough information. We also know that advanced developers don’t like to use plugins with tons of unnecessary code, just to add a simple meta boxes. Same applies for heavy external metabox libraries.

What is a Custom Meta Box?

Custom meta boxes allow users to add additional information to posts, pages and custom post types, apart from the default set of information that WordPress takes using default meta boxes. Plugins and Themes can use custom meta boxes to take additional structured user input.

Custom meta boxes can also be added to the dashboard and attached to the admin interface. WordPress dashboard widgets are actually meta boxes.

In addition to the meta boxes, you can also edit the contents and appearance of the Admin Bar that is seen by those who are logged in to the admin interface.

Editor, Custom Fields, Featured Image, Categories, and Tags on a post, page or custom post page admin interface are default meta boxes. They are created by the WordPress core.

Custom Meta Box vs Custom Fields

Custom fields allow users to add key/value pairs of data to a post, page or custom post type. But meta boxes can have many varieties of input fields such as color picker, file upload, drop downs, and so on.

Adding Meta Boxes to Post Types Screen

To add a meta box to the any post type editing screen, the add_meta_box() is used and subsequently hooked to theadd_meta_boxes action.

The code below adds a metabox to the post edit screen. Take note of js_code_notice_meta_box_cb, the function that is called to display the form field(s) in the meta box. We’ll come to that later.

if( ! function_exists( 'js_code_notice_meta_box' )){
	function js_code_notice_meta_box() {

        add_meta_box(
            'js-code-notice',
            __( 'JS Code Notice', 'textdomain' ),
            'js_code_notice_meta_box_cb',
            'post'
        );
	}
}

add_action( 'add_meta_boxes', 'js_code_notice_meta_box' );

To add a meta box to a number of post types screens – postpage and a book custom post type; create an array of the post types, iterate over the array and use add_meta_box() to add the meta box to them.

if( ! function_exists( 'js_code_notice_meta_box' )){
	function js_code_notice_meta_box() {

	    $screens = array( 'post', 'page', 'book' );

	    foreach ( $screens as $screen ) {
	        add_meta_box(
	            'js-code-notice',
	            __( 'JS Code Notice', 'textdomain' ),
	            'js_code_notice_meta_box_cb',
	            $screen
	        );
	    }
	}
}

add_action( 'add_meta_boxes', 'js_code_notice_meta_box' );

To add a meta box to all existing post types and those to be created in future, use get_post_types() to get an array of the post types and then replace the value of $screen above with it.

if( ! function_exists( 'js_code_notice_meta_box' )){
	function js_code_notice_meta_box() {

	    $screens = get_post_types();

	    foreach ( $screens as $screen ) {
	        add_meta_box(
	            'js-code-notice',
	            __( 'JS Code Notice', 'textdomain' ),
	            'js_code_notice_meta_box_cb',
	            $screen
	        );
	    }
	}
}

add_action( 'add_meta_boxes', 'js_code_notice_meta_box' );

Among the array argument used by register_post_type() for customizing a custom post type is the register_meta_box_cb in which its value is a callback function that is called when setting up the meta boxes.

Say we created a project custom post type with the following code:

if( ! function_exists( 'js_code_project_cpt' )){
	function js_code_project_cpt() {

	    $args = array(
	        'label'                => 'Projects',
	        'public'               => true,
	        'register_meta_box_cb' => 'js_code_meta_box_cpt_cb'
	    );

	    register_post_type( 'project', $args );
	}
}
add_action( 'init', 'js_code_project_cpt' );

Adding the add_meta_box() function definition for creating a meta box inside a js_code_meta_box_cpt_cb PHP function (value of register_meta_box_cb above) will add the meta box to the book custom post type edit screen.

And again, here is our example js_code_meta_box_cpt_cb function.

if( ! function_exists( 'js_code_meta_box_cpt_cb' )){
	function js_code_meta_box_cpt_cb() {

	    add_meta_box(
	        'js-code-notice',
            __( 'JS Code Notice', 'textdomain' ),
            'js_code_notice_meta_box_cb',
	    );

	}
}

So far, we’ve learned the various ways of registering or adding meta boxes to WordPress. We are yet to create the js_code_notice_meta_box_cb function that will contain the form field of our meta box.

Below is the code for the js_code_notice_meta_box_cb function that will include a text area field in the meta box.

if( ! function_exists( 'js_code_notice_meta_box_cb' )){
	function js_code_notice_meta_box_cb( $post ) {

	    // Add a nonce field so we can check for it later.
	    wp_nonce_field( '_js_code_notice_nonce', 'js_code_notice_nonce' );

	    $value = get_post_meta( $post->ID, '_js_code_notice', true );

	    echo '<textarea id="_js_code_notice" name="_js_code_notice">' . esc_attr( $value ) . '</textarea>';
	}
}

The save_post action hook handles saving the data entered into the text area when the post is saved as draft or published.

if( ! function_exists( 'save_js_code_notice_meta_box_data' )){
	/**
	 * When the post is saved, saves our custom data.
	 *
	 * @param int $post_id
	 */
	function save_js_code_notice_meta_box_data( $post_id ) {

	    // Check if our nonce is set.
	    if ( ! isset( $_POST['js_code_notice_nonce'] ) ) {
	        return;
	    }

	    // Verify that the nonce is valid.
	    if ( ! wp_verify_nonce( $_POST['js_codeglobal_notice_nonce'], '_js_code_notice_nonce' ) ) {
	        return;
	    }

	    // If this is an autosave, our form has not been submitted, so we don't want to do anything.
	    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
	        return;
	    }

	    // Check the user's permissions.
	    if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) {

	        if ( ! current_user_can( 'edit_page', $post_id ) ) {
	            return;
	        }

	    }
	    else {

	        if ( ! current_user_can( 'edit_post', $post_id ) ) {
	            return;
	        }
	    }

	    /* OK, it's safe for us to save the data now. */

	    // Make sure that it is set.
	    if ( ! isset( $_POST['js_code_notice'] ) ) {
	        return;
	    }

	    // Sanitize user input.
	    $js_code_data = sanitize_text_field( $_POST['js_code_notice'] );

	    // Update the meta field in the database.
	    update_post_meta( $post_id, '_js_code_notice', $js_code_data );
	}
}
add_action( 'save_post', 'save_js_code_notice_meta_box_data' );

To put the data that would be entered into the meta box text area to use, we’ll display the data before the post content that it’s saved against is displayed.

if( ! function_exists( 'js_code_notice_before_post' )){
	function js_code_notice_before_post( $content ) {

	    global $post;

	    // retrieve the js_code notice for the current post
	    $js_code_notice = esc_attr( get_post_meta( $post->ID, '_js_code_notice', true ) );

	    $notice = "<div class='your-class'>$js_code_notice</div>";

	    return $notice . $content;

	}
}
add_filter( 'the_content', 'js_code_notice_before_post' );

Code Explanation

First, we created a js_code_notice_before_post function hooked into the_content filter with a $content parameter which contains the post content.

Inside the function, we include the global $post variable that contains the WP_Post object of the current post that is being viewed.

The global notice saved against a given post is retrieved by get_post_meta and saved to $js_code_notice variable.

The notice is then wrapped in a div and saved to the $notice variable.

And finally, $notice which holds the global notice is concatenated to $content which is the actual post content.

Below is a screenshot of a post with the global notice before the post content.

Wrap Up

In this article, we showed a number of ways to register meta boxes to WordPress administrative screens and how to restrict them to post types.

We also reviewed how to add form fields to a meta box and how to save data entered into it when a post is saved or published.

Finally, we covered how to put into practical use the data entered into a meta box.

I hope you’ve enjoyed the tutorial. Feel free to post questions about creating meta boxes in the comments.

Happy coding!

JSC0d3's Logo
About JSC0d3

JSC0d3 is an entrepreneur, online marketer, and an employee of an IT company. When not building websites, creating content, or helping customers improve their online business, spend time with their wife and two beautiful children. Although he still feels new in WordPress, he enjoys sharing what he has learned with all of you! If you want to get in touch with him, you can do this through this website.

On the same idea

Posted by | February 9, 2019

How fast your website loads can have a direct effect on whether you turn visitors into new customers and fans When your site is delivered to...

Posted by | February 9, 2019

With today’s high-speed internet connections and advances in web development techniques, there is no reason that your website should be...

Posted by | February 9, 2019

WordPress' wp_link_pages() function, used for displaying page links in multi-page posts, lacks one big feature You can display a list of...

Previous PostBackNext Post

Leave here an impression