The WordPress posts edit Tool is not an unique compact module that shows all the boxes that appear on the screen but it’s a set of different little modules –called metaboxes– working together. A little module controls the title, another one controls the visual editor, another one defines the publishing options and actions, another one is for the Post Format… the Categories, the Author’s post, etc. The reason of this modular design is to allow developers to introduce easily new boxes (or remove some ones) in the Edit Screen.
So thanks to this modular design, we can create our metaboxes for adding new functionalities or data to the WordPress Posts. The complete method for developing a new metabox has these three steps:
- To inform that a new metabox has to be included in the Posts Edit Module.
- To write the metabox function (for example two simple fields for selecting among 5 different colors and sizes).
- To write a function for saving the new data (color and size) with the rest of common post data as two new meta values.
Let’s go to see these three steps.
To inform that a new metabox has to be included in the Posts Edit Module
In this first step, we have to inform to WordPress that we want to include a new metabox in the edit screen of posts and that there is a new function that controls this new metabox… For doing this step, there are some ways, in fact it’s possible to do this step with just a couple of code lines however, in this example we’ll see the official long way.
The first part of this step is attaching a new function adding_metaboxes_to_editPosts
to the action current_screen
that controls the load of all screens in WordPress environment and always receives one parameter: the current screen as a WP_Screen Object. Obviously, we could go straightly to the second step but sometimes, in a more complex situations probably we want to control the load of metaboxes from the beginning so that’s the real beginning: the action current_screen
.
<?php function adding_metaboxes_to_editPosts ( $screen ) { // When we need, we can introduce some control over the $screen object, for example //if ( $screen->base != 'post' ) return;
// for controling that this new metabox is just loaded in case of posts. // Or for distinguishing between a new post and an old post //if ( $screen->action == 'add' ) return;
// etc. $page = $screen->base; add_action( "load-$page.php", 'load_our_environment' ); // for old post add_action( "load-$page-new.php", 'load_our_environment' ); // for new post // or, // add_action( "load-$page-new.php", 'load_our_environment_for_new_posts
' ); } if ( is_admin() ) // add_action ( 'current_screen', 'adding_metaboxes_to_editPosts', 10, 1 ); ?>
As you can see, if we use the action current_screen
we can easily introduce all kinds of check and verification points in our code that help us to construct specific environtments for each case, ie, for example, in case of new item, in case of old item, in case of special post type, in case of etc. Take a look to the WP_Screen Object for further information in the official documentation.
The second part is to use the action(s) that specíficaly loads each one of the WP screens: the action load-$page
. In our example, we’ll use this action for two things:
- To attach the function that attaches the metabox(es) to the Post Edit Screen.
- To attach the function(s) that will save the new data (in our example, color and size).
As I said in the first part of this step, these final functions can be called directly in the functions.php but it’s always better to call them inside the functions that are executed inside the correct hooks.
<?php
function saving_the_metabox_data ( $post_id, $post, $update ) {
// we'll develop this function later
}
function loading_the_metabox ( $post_type, $post ) {
add_meta_box(
'the-metabox-id', // this ID must be unique
__( 'Your personal options', 'textdomain' ),
'render_metabox_callback_function', // the name of the function used to display the metabox
$post_type,
'advanced',
'default',
NULL, // or $post, or whatever addtional parameters you need pass to the callback function
);
}
function load_our_environment () {
add_action( 'add_meta_boxes', 'loading_the_metabox', 10, 2 );
// if you want, you can also use add_meta_boxes_{post_type}
that just receives one parameter, the $post
add_action( 'save_post', 'saving_the_metabox_data', 10, 3 );
}
?>
By the way, the official documentation of the action add_meta_box
for a deeper look at all its parameters is here.
To write the metabox function code
In the second step, we’ll write the function that renders the metabox inside the Posts Edit Module. This (and all) metabox(es) render function(s) always receives two parameters, the current $post (in general an object), and the array of values defined in the last parameter of the action add_meta_box. So we’re going to use both of them so, first we’ll rewrite the former metabox call, and then we write our render_metabox_callback_function
<?php // we rewrite the function thatactives
the new metabox function loading_the_metabox ( $post_type, $post ) { add_meta_box( 'the-metabox-id', // this ID must be unique __( 'Your personal options', 'textdomain' ), 'render_metabox_callback_function', // the name of the function used to display the metabox $post_type, 'advanced', 'default', // in the next lines we define the parameters the function receivesarray ( 'defaColo' => 'black', 'colors' => array ( 'white' => __ ( 'White', 'textdomain' ), 'black' => __ ( 'Black', 'textdomain' ), 'red' => __ ( 'Red', 'textdomain' ), 'blue' => __ ( 'Blue', 'textdomain' ), 'yellow' => __ ( 'Yellow', 'textdomain' ) ), 'defaSize' => 'medium', 'sizes' => array ( 'x-small' => __ ( 'Extra Small', 'textdomain' ), 'small' => __ ( 'Small', 'textdomain' ), 'medium' => __ ( 'Medium', 'textdomain' ), 'large' => __ ( 'Large', 'textdomain' ), 'x-large' => __ ( 'Extra Large', 'textdomain' ) ) )
); } // Now, the function thatrenders
the new metabox function render_metabox_callback_function ( $post, $data ) { $color = get_post_meta ( $post->ID, 'color', TRUE ); $size = get_post_meta ( $post->ID, 'size', TRUE ); // In case of a new post or if the current post hasn't got a defined color or size, // we use the array $data for setting the default value(s). if ( ! $color ) $color = $data['args']['defaColo']; if ( ! $size ) $size = $data['args']['defaSize']; // We construct the list of options $clist = $data['args']['colors']; $slist = $data['args']['sizes']; // // the nonce field will be here // // and now two simple select fields echo '<p><label for="theColor">' . __( 'Select your Color', 'textdomain' ) . '</label> '; echo '<select name="theColor
" id="theColor" value="' . $color . '">'; foreach ( $clist as $c => $value ) echo '<option value="' . $c . '" ' . selected ( $c, $color, false ) . ' >' . $value . '</option>'; echo '</select></p>'; echo '<p><label for="theSize">' . __( 'Select your Size', 'textdomain' ) . '</label> '; echo '<select name="theSize
" id="theSize" value="' . $size . '">'; foreach ( $slist as $s => $value ) echo '<option value="' . $s . '" ' . selected ( $s, $size, false ) . ' >' . $value . '</option>'; echo '</select></p>'; } ?>
Now, in the Edit Screen of Posts you can see the new metabox,
that works like this next code example.
So, now it’s time for the last step: to save this new data –color and size– as a new meta values for each post.
To write a function for saving this new data
In this step, we’ll write a function that saves these two new values. The name of the function has been decided and attached to the action save_post
in the first step so, now, we can directly rewrite the former minimal function saving_the_metabox_data
for converting it into a real function.
This function can be very sophisticated because we can introduce a lot of checking points in it: nonce values, privileges and roles, etc. however now, for understanding how does it work, we’ll begin with a simple function that just saves these two values: theColor
, and theSize
.
<?php function saving_the_metabox_data ( $post_id, $post, $update ) { // the function just checks the existence of the valuestheColor
andtheSize
// in PHP $_REQUEST array and saves the values as a new meta for the post // whose ID = $post_id. if ( isset( $_REQUEST['theColor'] ) ) update_post_meta( $post_id, 'color', $_REQUEST['theColor'] ); if ( isset( $_REQUEST['theSize'] ) ) update_post_meta( $post_id, 'size', $_REQUEST['theSize'] ); } ?>
This is the basic core of the saving function, that simply checks and saves the values so from this core, if we add this next line to the function render_metabox_callback_function
to the marked point tfor introducing a hidden nonce field,
wp_nonce_field( 'myoptions_nonce_action', 'myoptions_nonce' );
we can develop our final saving function with all checking points.
<?php
function saving_the_metabox_data ( $post_id, $post, $update ) {
// Firtsly we retreive the value of the hidden nonce field
$nonce_name = isset( $_POST['myoptions_nonce'] ) ? $_POST['myoptions_nonce'] : '';
$nonce_action = 'myoptions_nonce_action';
// and then, we can check if nonce is set.
if ( ! isset( $nonce_name ) ) return;
// afterwards, if nonce is valid.
if ( ! wp_verify_nonce( $nonce_name, $nonce_action ) ) return;
// Here, if ew need it, we can also introduce a user's capabilities checking point
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
// At this point, as the official documentation suggests for 'save_post' action,
// we can check if the save action is an background 'autosave' action or a real user's submit
// and also, if it is just a 'revision' or the real last post version.
// We check if it's not an autosave.
if ( wp_is_post_autosave( $post_id ) ) return;
// We check if it's not a revision.
if ( wp_is_post_revision( $post_id ) ) return;
// Finally, if we need it, we could check the value of the third parameter $update
// for choosing two different procedures: a procedure in case of new post and another one in case
// of updating an existing post.
// if ( $update )
// call_function_old_post();
// else
// call_function_new_post();
// Here, we save the new data
if ( isset( $_REQUEST['theColor'] ) )
update_post_meta( $post_id, 'color', $_REQUEST['theColor'] );
if ( isset( $_REQUEST['theSize'] ) )
update_post_meta( $post_id, 'size', $_REQUEST['theSize'] );
}
?>
And that’s all, now we can already use these new values in our Themes via the function get_post_meta
.
<?php echo get_post_meta( get_the_ID(), 'color', TRUE ); ?>
I hope this ‘step by step’ approach can help you to develop easily a better metaboxes.
Have a nice WordPressing!
you are truly a good webmaster. The web site loading velocity is amazing. It sort of feels that you are doing any distinctive trick. Moreover, The contents are masterwork. you’ve done a wonderful task in this matter!
Thanks, Clifford. And yes, I’ve been working in some load tricks.
I’m glad you like it.
Best,
Joan Miquel
constantly i used to read smaller content that also clear their motive, and that is also
happening with this article which I am reading now.
My web-site http://www.quantumblah.org/
Thanks Peggy, I hope you don’t entangle with it.
Joan Miquel
[…] few days ago, we was talking about how to construct a WordPress metabox for a couple of fields, today we will extend that example with several examples of code for adding different kinds of […]
[…] is saved to database and disc storage. In fact, at the end, we are doing the same that with fields created via metabox: a function for displaying, and a function for saving the […]
[…] with the example of yesterday (How to add a Metabox. A step by step approach.), now we’re going to add a checkbox field for controlling whether this person lives in CA or […]