What are Meta Boxes Exactly?
Meta boxes are UI blocks in WordPress admin that allow you to manage post metadata.
Okay, what is metadata?
Every type of content in WordPress like posts, terms, users and comments has its own table in WordPress database, wp_posts
, wp_terms
, wp_users
and wp_comments
accordingly. Those tables are intended to store some default data, like post title and publish date for posts.
But what if you need to store something super-custom? Like a SEO-title for posts or an age for users or… product price for products? The answer is – metadata. WordPress also has specific database tables for that – wp_postmeta
, wp_termmeta
, wp_usermeta
, wp_commentmeta
.
Add Custom Meta Box
Let me show you how to create a meta box in WordPress, here is a screenshot of what we are going to create:
Step 1. add_meta_box()
Function add_meta_box()
should be called inside an action hook, there are 3 options:
admin_menu
add_meta_boxes
add_meta_boxes_{post_type}
– here you can specify a specific post type name, e.g.add_meta_boxes_page
– so the code will only run when editingpage
post type.
add_action( 'admin_menu', 'atdev_add_metabox' );
// or add_action( 'add_meta_boxes', 'atdev_add_metabox' );
// or add_action( 'add_meta_boxes_{post_type}', 'atdev_add_metabox' );
function atdev_add_metabox() {
add_meta_box(
'atdev_metabox', // metabox ID
'Meta Box', // title
'wpdev_metabox_callback', // callback function
'page', // add meta box to custom post type (or post types in array)
'normal', // position (normal, side, advanced)
'default' // priority (default, low, high, core)
);
}
// it is a callback function which actually displays the content of the meta box
function atdev_metabox_callback( $post ) {
echo 'hey';
}
Insert above code in your theme functions.php or in a custom plugin.
Step 2. Callback function with meta box HTML
Now populate the meta box with custom fields.
function atdev_metabox_callback( $post ) {
$seo_title = get_post_meta( $post->ID, 'seo_title', true );
$seo_robots = get_post_meta( $post->ID, 'seo_robots', true );
// nonce, actually I think it is not necessary here
wp_nonce_field( 'atdev_security', '_atdevnonce' );
echo '<table class="form-table">
<tbody>
<tr>
<th><label for="seo_title">SEO title</label></th>
<td><input type="text" id="seo_title" name="seo_title" value="' . esc_attr( $seo_title ) . '" class="regular-text"></td>
</tr>
<tr>
<th><label for="seo_robots">SEO robots</label></th>
<td>
<select id="seo_robots" name="seo_robots">
<option value="">Select...</option>
<option value="index,follow"' . selected( 'index,follow', $seo_robots, false ) . '>Show for search engines</option>
<option value="noindex,nofollow"' . selected( 'noindex,nofollow', $seo_robots, false ) . '>Hide for search engines</option>
</select>
</td>
</tr>
</tbody>
</table>';
}
In the code above:
- I used function
get_post_meta()
to get the existing meta fields values and display them. wp_nonce_field()
is needed for additional security, when we save our meta box data, we can check the nonce value to make sure that the request come from the proper place.selected()
is a build-in WordPress function that simplifies the conditions and displayingselected="selected"
in the<select>
field.
Step 3. Save meta box data
If you are using this metabox on the page edit screen or for a custom post type, don’t forget to redefine supported post types, otherwise metabox data won’t be saved.
add_action( 'save_post', 'atdev_save_meta', 10, 2 );
// or add_action( 'save_post_{post_type}', 'atdev_save_meta', 10, 2 );
function atdev_save_meta( $post_id, $post ) {
// nonce check
if ( ! isset( $_POST[ '_atdevnonce' ] ) || ! wp_verify_nonce( $_POST[ '_atdevnonce' ], 'atdev_security' ) ) {
return $post_id;
}
// check current user permissions
$post_type = get_post_type_object( $post->post_type );
if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) ) {
return $post_id;
}
// Do not save the data if autosave
if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
return $post_id;
}
// define your own post type here
if( 'page' !== $post->post_type ) {
return $post_id;
}
if( isset( $_POST[ 'seo_title' ] ) ) {
update_post_meta( $post_id, 'seo_title', sanitize_text_field( $_POST[ 'seo_title' ] ) );
} else {
delete_post_meta( $post_id, 'seo_title' );
}
if( isset( $_POST[ 'seo_robots' ] ) ) {
update_post_meta( $post_id, 'seo_robots', sanitize_text_field( $_POST[ 'seo_robots' ] ) );
} else {
delete_post_meta( $post_id, 'seo_robots' );
}
return $post_id;
}
Please keep in mind, that depending on your field type you must use sanitization, so in the above example I am using sanitize_text_field()
function, but there are also another ones, like sanitize_textarea()
for textarea fields, sanitize_email()
etc.
Also it is also not necessary to use delete_post_meta()
for some cases, for example for regular text fields. But isset()
or empty()
condition checks are still recommended because you would get PHP notices if a field value will be empty.
$seo_title = isset( $_POST[ 'seo_title' ] ) ? sanitize_text_field( $_POST[ 'seo_title' ] ) : '';
update_post_meta( $post_id, 'seo_title', $seo_title );
Have fun coding!
Very nice post. I just stumbled upon your weblog and wanted to say that I have really enjoyed
surfing around your blog posts. In any case I will be subscribing to your rss feed and I hope
you write again soon!