Try Tuts+ Premium, Get Cash Back!
How to Create Custom WordPress Write/Meta Boxes

How to Create Custom WordPress Write/Meta Boxes

Tutorial Details
  • Program: WordPress
  • Version: 3.2
  • Difficulty: Intermediate to Advanced
  • Estimated Completion Time: 30 minutes
This entry is part 4 of 6 in the series WordPress Dashboard Customizations

Creating meta boxes is a crucial part of WordPress theme/plugin development. It’s a way to add an appealing editor to the post screen and avoids forcing users to rely on custom fields. If you’ve ever created a custom post type in WordPress, you’ve probably wanted to add some sort of additional data to it. Sure, you could use custom fields, but that’s ugly. Getting started with custom meta boxes is easy, so let’s dive in!


What Are Custom Meta Boxes?

A custom meta (or write) box is incredibly simple in theory. It allows you to add a custom piece of data to a post or page in WordPress.

Imagine that you’re working on a theme for a client that wants to catalog his extensive collection of concert posters. You immediately start looking to the core WordPress functionality to see how you might organize the theme: Every post will represent a poster, which is perfect for adding an image, title and description. We can also use the categories and tags system inside of WordPress to organize the posters. But what if we wanted to add a new type of meta data for the “artist” of each poster? Hmph. WordPress doesn’t quite have anything for that right out of the box… which brings us to custom meta boxes.

A custom meta (or write) box is incredibly simple in theory. It allows you to add a custom piece of data to a post or page in WordPress – what’s better is that it can fit directly into most of the default pages inside WP, so you can easily place it inside the Post-Editor for easy use by non-technical types. As I said in the intro, you can add this same kind of “meta data” to your post using the built in custom fields for a post or page. There’s nothing wrong with this persay, but it’s not a very graceful or user-friendly.

Instead, you want to create a custom meta box that contains fields for all of your data and saves all of that stuff right when the post is published. That’s what we’re covering here. This is broken down into three big steps:

  • Adding the meta box
  • Rendering the meta box
  • Saving the data (the right way – yes, there is a wrong way)

It’s worth noting that a lot of this information can also be used inside the custom post types API (we’ll get to that point later!), but for the sake of keeping things focused today, we’re going to add this directly to the default post editor.

For the advanced readers in the audience: Yes, custom post types is where we’ll be going with this eventually, but it’s important to setup some fundamentals first. Plus, as you can use the custom meta boxes in all sorts of places, it’s good for anyone to know.

Anything in this tutorial will work in a theme’s functions.php file. That is not the correct place for it, however. If you’re adding data to a post, chances are you want it there regardless of your front end design. As such, you should place this code some place that isn’t dependent on your design: a plugin file.


Step 1 Adding the Meta Box

The Meta Box Title

Conveniently, WordPress provides a function for adding meta boxes to a given admin screen: add_meta_box.

The codex entry is well done for this function, but here’s a brief overview. Its prototype:

<?php add_meta_box( $id, $title, $callback, $page, $context, $priority, $callback_args ); ?>

$id is the html ID attribute of the box. This is useful if you’re loading custom CSS or Javascript on the editing page to handle the options. Otherwise, it doesn’t really matter all that much.

$title is displayed at the top of the meta box.

$callback is the function that actually renders the meta box. We’ll outline this in step 2.

$page is where you want the meta box to be displayed. This should be a string with ‘post’ or ‘page’ or ‘some_custom_post_type’.

$context is where you want the meta box displayed. ‘normal’ puts it below the post editor. ‘side’ moves the meta box to editing screen’s right sidebar (by the categories and tags, etc). ‘advanced’ also put the box in the same column as the post editor, but further down.

$priority tells wordpress where to place the meta box in the context. ‘high’, ‘default’ or ‘low’ puts the box closer to the top, in its normal position, or towards the bottom respectively. Since all meta boxes are drag-able, $priority is not a huge deal.

Finally $callback_args lets you pass data to your $callback function in the form of an array. We’re not going to use this here, but it could be useful for passing some data to the meta box. Say, if your plugin had several options that influenced what was displayed in the meta box. You could pass those options values through the $callback_args array.

So, our add_meta_box call will look like this:

<?php add_meta_box( 'my-meta-box-id', 'My First Meta Box', 'cd_meta_box_cb', 'post', 'normal', 'high' ); ?>

We can’t just pop this into our plugin file alone. Doing so will result in the white screen of death, and PHP fatal error: call to undefined function. Why? Because we called add_meta_box function before WordPress was loaded. So we need to use a WordPress hook, which is part of the plugin api. Basically, functions get hooked into a given WordPress action or filter hook, then those functions are fired when that hook loads. By wrapping our add_meta_box call in a function, then hooking that function into the add_meta_boxes action hook, we avoid the fatal error.

Our code to add the meta box to our post screen would look like this:

<?php
add_action( 'add_meta_boxes', 'cd_meta_box_add' );
function cd_meta_box_add()
{
	add_meta_box( 'my-meta-box-id', 'My First Meta Box', 'cd_meta_box_cb', 'post', 'normal', 'high' );
}
?>

Step 2 Rendering the Meta Box

The above code is enough to add the meta box, but now we have to render the thing and actually add fields. This is just an HTML form code mixed in with a bit of PHP to display the saved data. We don’t need to include the form tags as WordPress does that for us.

Remember the string we passed as the $callback in add_meta_box? We’re now going to create a function with the same name. This function will take care of all the display inside the meta box.

<?php
function cd_meta_box_cb()
{
	echo 'What you put here, show\'s up in the meta box';	
}
?>

We’re going to add several fields to our meta box: a text input, a drop down menu, and a check-box. Let’s start with the text input.

Adding the Text Input

<?php
function cd_meta_box_cb()
{
	?>
	<label for="my_meta_box_text">Text Label</label>
	<input type="text" name="my_meta_box_text" id="my_meta_box_text" />
	<?php	
}
?>

But what about actually displaying the data? Well, as you’ll see in step 3, we’ll store this data in the wp_postmeta table using the update_post_meta function. That function has two sister functions called get_post_meta and get_post_custom, which grab data from wp_postmeta. get_post_meta only grabs data from one key, while get_post_custom grabs all of it. Because we’re only really using one field at this point, let’s use get_post_meta.

Also note that the add_meta_box function passes one variable to our callback: $post, which is a post object.

<?php
function cd_meta_box_cb( $post )
{
$values = get_post_custom( $post->ID );
$text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ”;
$selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'][0] ) : ”;
$check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'][0] ) : ”;
	?>
<p>
	<label for="my_meta_box_text">Text Label</label>
	<input type="text" name="my_meta_box_text" id="my_meta_box_text" value="<?php echo $text; ?>" />
        </p>
	<?php		
}

?>

Adding The Drop Down

<?php	
function cd_meta_box_cb( $post )
{
$values = get_post_custom( $post->ID );
$text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ”;
$selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'][0] ) : ”;
$check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'][0] ) : ”;
	?>
	<p>
		<label for="my_meta_box_text">Text Label</label>
		<input type="text" name="my_meta_box_text" id="my_meta_box_text" value="<?php echo $text; ?>" />
	</p>
	
	<p>
		<label for="my_meta_box_select">Color</label>
		<select name="my_meta_box_select" id="my_meta_box_select">
			<option value="red" <?php selected( $selected, 'red' ); ?>>Red</option>
			<option value="blue" <?php selected( $selected, 'blue' ); ?>>Blue</option>
		</select>
	</p>
	<?php	
}
?>

With the addition of a second field, we changed or get_post_meta call to get_post_custom, which returns an associative array of all the post’s custom keys and values. We then just access our fields via their names. The ternary statements keep our code from throwing PHP warnings (undefined indices and such). We’ll cover the esc_attr function in step three.

In the drop down, we’re going to use one of WordPress’s most handy functions: selected. This compares the first value, the data we saved, with the second, the <option>‘s value attribute. If they’re the same, the function will echo selected="selected", which makes that value display on the drop down. Pretty sweet, and it saves us from writing a bunch of if or ternary statements. You can also use the selected() function with radio buttons.

Adding the Check-box

&lt?php
function cd_meta_box_cb()
{
	// $post is already set, and contains an object: the WordPress post
	global $post;
	$values = get_post_custom( $post->ID );
	$text = isset( $values['my_meta_box_text'] ) ? $values['my_meta_box_text'] : '';
	$selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'] ) : '';
	$check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'] ) : '';
	
	// We'll use this nonce field later on when saving.
	wp_nonce_field( 'my_meta_box_nonce', 'meta_box_nonce' );
	?>
	<p>
		<label for="my_meta_box_text">Text Label</label>
		<input type="text" name="my_meta_box_text" id="my_meta_box_text" value="<?php echo $text; ?>" />
	</p>
	
	<p>
		<label for="my_meta_box_select">Color</label>
		<select name="my_meta_box_select" id="my_meta_box_select">
			<option value="red" <?php selected( $selected, 'red' ); ?>>Red</option>
			<option value="blue" <?php selected( $selected, 'blue' ); ?>>Blue</option>
		</select>
	</p>
	
	<p>
		<input type="checkbox" id="my_meta_box_check" name="my_meta_box_check" <?php checked( $check, 'on' ); ?> />
		<label for="my_meta_box_check">Do not check this</label>
	</p>
	<?php	
}
?>

Again WordPress provides the handy function checked(). It works just like selected() comparing the first value (our saved data) to the second and echoing out checked="checked" if they’re the same.

wp_nonce_field adds two hidden fields to our meta box. One of them is a nonce. These are random strings of numbers that are valid on per user per blog basis for 24 hours. Nonces are a way of verifying intention, and they make sure that WordPress doesn’t do anything unless the request came from a very specific place. In other words, we don’t want to accidentally update our data by somehow running our save function (see step 3) in another location other than the save_post hook, so we check to make sure the nonce is valid before doing anything.

Step 3 Saving the Data

The number one rule when putting anything into your database or on your site is don’t trust the user. Even if that user is you.

To save our data, we’re going to rely on another WordPress hook: save_post. This works just like our action hook above:

<?php add_action( 'save_post', 'cd_meta_box_save' ); ?>

The cd_meta_box_save function will receive one argument, the post id, and take care of cleaning and saving all of our data. The save_post hook fires after the update or save draft button has been hit. So we have access to all the $_POST data, which includes our meta box fields, within our saving function. Before we can do anything, however, we have to do three things: check if the post is auto saving, verify the nonce value we created earlier, and check to make sure the current user can actually edit the post.

<?php
add_action( 'save_post', 'cd_meta_box_save' );
function cd_meta_box_save( $post_id )
{
	// Bail if we're doing an auto save
	if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
	
	// if our nonce isn't there, or we can't verify it, bail
	if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;
	
	// if our current user can't edit this post, bail
	if( !current_user_can( 'edit_post' ) ) return;
}
?>

Now the fun stuff: actually saving our data. The number one rule when putting anything into your database or on your site is don’t trust the user. Even if that user is you. To that end, before we save any data, we want to make sure there’s nothing malicious in there. Fortunately WordPress provides a bunch of functions for data validation.

You already saw esc_attr() above (step 2). This one encodes ‘ ” and < > into HTML entities. Why use this? So users couldn’t type a <script> into your meta box. If you’d like to allow certain HTML tags in, but strip others, wp_kses can do that. It takes two arguments, the first of which is the string you’d like to check and the second is an associative array of allowed tags. WordPress provides many more data validation tools, just don’t be afraid to use them.

We’re going to use the update_post_meta function to date care of saving our data. It takes three arguments: a post ID, the meta key, and the value.

<?php
add_action( 'save_post', 'cd_meta_box_save' );
function cd_meta_box_save( $post_id )
{
	// Bail if we're doing an auto save
	if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
	
	// if our nonce isn't there, or we can't verify it, bail
	if( !isset( $_POST['meta_box_nonce'] ) || !wp_verify_nonce( $_POST['meta_box_nonce'], 'my_meta_box_nonce' ) ) return;
	
	// if our current user can't edit this post, bail
	if( !current_user_can( 'edit_post' ) ) return;
	
	// now we can actually save the data
	$allowed = array( 
		'a' => array( // on allow a tags
			'href' => array() // and those anchors can only have href attribute
		)
	);
	
	// Make sure your data is set before trying to save it
	if( isset( $_POST['my_meta_box_text'] ) )
		update_post_meta( $post_id, 'my_meta_box_text', wp_kses( $_POST['my_meta_box_text'], $allowed ) );
		
	if( isset( $_POST['my_meta_box_select'] ) )
		update_post_meta( $post_id, 'my_meta_box_select', esc_attr( $_POST['my_meta_box_select'] ) );
		
	// This is purely my personal preference for saving check-boxes
	$chk = isset( $_POST['my_meta_box_check'] ) && $_POST['my_meta_box_select'] ? 'on' : 'off';
	update_post_meta( $post_id, 'my_meta_box_check', $chk );
}
?>

Wrap Up

That’s it! You should have a fully working meta box. Other examples you may find around the web loop through a bunch of fields without really cleaning the data. This is the wrong approach. Always use the built in data validation functions; different fields/values may require different data validation.

To use these custom fields on the front end of your site, use the get_post_meta or get_post_custom functions (see step 2).


Other parts in this series:Customizing the WordPress Dashboard For Your ClientsThree Practical Uses for Custom Meta Boxes
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://thedevelopertuts.com Bratu Sebastian

    Interesting tutorial ,thanks!

    I need to implement nonce in my cms too :)

  • http://www.xpertdeveloper.com Avi

    Good One :)

  • http://naghies.ir Behrang

    Really Useful…Thanks!

  • http://www.supersixtwo.com Troy Peterson

    So, I have a question when saving the data… maybe someone can explain.

    If we verify the field using isset(), if the form was empty, it will still add a meta field in the db, but it will be empty.

    At first, It thought using !empty(), but that doesn’t help if we want to go back and delete the contents of the field. It will say it’s empty and won’t update the meta entry.

    So, what is the best way to actually check if the file was the same as the original and only update if it’s different?

    Thanks!
    Troy

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      update_post_meta() takes an option fourth argument that is the old value you wish to replace:

      so…

      $old = get_post_meta( $post->ID, ‘my_meta_box_text’, true );
      update_post_meta( $post->ID, ‘my_meta_box_text, $new, $old );

      where $new is the from the data you’re saving.

  • http://www.sitestore.co.il Shir Gans

    That’s a good topic since many developers already reached the level of customizing not only the front-end but also the back-end. But I think it worth mention how to create these meta boxes more easily, maybe by a class (.. wpalchemy), and how to load meta boxes by the theme name.
    Cheers !

  • Robert

    Really Great tutorial.

    I enjoy all of your wp tutorials and allthough it’s a new section of tutplus i am allready a very big fan of wp.tutplus.com

    Keep up the great work

  • Andrew

    Is there any chance you could follow this up with how to add date-field boxes for creating a diary of events calendar?

  • Ab

    Hi. As soon as I add html for the text input to functions.php it breaks my site. I know you suggest it could be used as a plug-in, but I need it in my theme file. Please can you help by showing how to do this?

  • http://kylephelps.net Kyle

    Thanks for the great tutorial.

  • http://www.osura.com Anton Korzhuk

    finally a good tutorial about meta boxes. thanks for posting this!

  • Michael

    wpTuts+ | A great addition to the “+” family, and this article a fine example.

    I do have one critique however— not about the post per se, but rather, the proof-reading. Persay was a big speed-bump to my eyes for some reason, and it made me stop to wonder if I had discovered yet another way of spelling “per se”.

    Other than those picayune/minor ‘let’s get it totally right’ details mentioned above, the “+” family is a great investment. Thanks for everything and keep’m coming.

    :)

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      I don’t even remember writing that one! Might have been an editor addition.

      Glad you liked the tutorial!

  • http://plr-diva.com Selena

    If you ever had to explain custom fields to a client, you’ll appreciate this tutorial. =) I’m going to implement this right away! WP Tuts is quickly becoming my favorite of all TutsPlus sites… Keep it coming, guys!

  • Adam

    Very nice tutorial Chris!

    However, is anyone else having issues with getting the drop-down or checkbox to save when publishing/updating a post? I believe there is a small typo in the ‘cd_meta_box_save’ function (I think ‘meta_meta_box_check’ should actually be ‘my_meta_box_check’) but that didn’t seem to fix the problem.

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      Good catch!

      There’s two issues that I missed. You’re right ont he save function, the last part should be…

      $chk = ( isset( $_POST['my_meta_box_check'] ) && $_POST['my_meta_box_check'] ) ? ‘on’ : ‘off’;
      update_post_meta( $post_id, ‘my_meta_box_check’, $chk );

      After you change that, the data does actually get saved, but I missed something else!

      get_post_custom returns an associative array where all the values are arrays. So my variables that are storing the data from the meta box are wrong, here’s what they should be:

      function cd_meta_box_cb( $post )
      {
      $values = get_post_custom( $post->ID );
      $text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ”;
      $selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'][0] ) : ”;
      $check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'][0] ) : ”;
      // etc.
      }

      • http://thomasblood.us Thomas

        Chris,

        When you corrected your associative array in the tutorial, you missed replacing the erroneous code in the “Adding the Check-box” section. This section still shows:

        $text = isset( $values['my_meta_box_text'] ) ? $values['my_meta_box_text'] : ”;
        $selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'] ) : ”;
        $check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'] ) : ”;

        Cheers,
        Thomas

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      Also, I emailed the wptuts folks and hopefully we can get the code changed in the article and in the plugin file attached.

      Sorry for the confusion everyone!

      -Chris

      • Brandon Jones

        Fixed and updated :) Thanks for the revision Chris!

  • http://www.beforesite.com Rew

    If you want to hide the Meta Box’s fields from WordPress’s custom fields panel.

    Use an underscore in the meta variable’s name to prevent it from showing up in the custom fields section

    For example change ‘my_meta_box_text’ to ‘_my_meta_box_text’

    Thanks for the Tut!

  • http://www.benedictgraphico.com/ John

    Very very useful. I’ve been using Custom Fields for far too long. Easy for me to get – but not so much for the less tech savvy clients. This will make my life much easier.

    Definitely looking forward to more tuts like this!

  • Brendan

    How do I make this show on the front end of the site?

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      Brendan,

      You can use get_post_meta() to grab the data. So, somewhere within the loop….

      if( get_post_meta( $post->ID, ‘my_meta_box_text’, true ) )
      {
      echo get_post_meta( $post->ID, ‘my_meta_box_text, true ) );
      }

      • http://wpchannel.com/ Aurélien Denis

        Hi,

        I put the code in the functions.php and change it to works with my custom post type.

        I also paste in my loop your code but it doesn’t display anything…

        if( get_post_meta( $post->ID, ‘my_meta_box_text’, true ) )
        {
        echo get_post_meta( $post->ID, ‘my_meta_box_text, true ) );
        }

        I think a more detailed explanations of how to show content of those custom fields shoud be awesome. ;)

  • Petro

    Hey, thanks for a grate tut! This is the simplest way of adding meta boxes.
    One question – how can i add the same meta boxes to various places. Lets say to post, and 2 post types. I’ve tried making: array(‘post’, ‘post type’, ‘post type’). but i get a bunch of errors. (debug mod is set on true)

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      Petro,

      Change the function you hook into add_meta_boxes to…

      add_action( ‘add_meta_boxes’, ‘cd_meta_box_add’ );
      function cd_meta_box_add()
      {
      foreach( get_post_types() as $type )
      {
      if( in_array( $type, array( ‘attachment’, ‘nav_menu_item’, ‘revision’ ) ) continue;
      add_meta_box( ‘my-meta-box-id’, ‘My First Meta Box’, ‘cd_meta_box_cb’, $type, ‘normal’, ‘high’ );
      }
      }

      • http://www.christopherguitar.net/wordpress/ Chris
        Author

        Let’s try that again: http://pastie.org/2240257

        More readable.

        • Brandon Jones

          Much better :) Go Pastie!

  • Pingback: [toread] How to Create Custom WordPress Write/Meta Boxes | Wptuts+ | D3sordr3

  • juanvi

    Nice tutorial!!!! Love it!

  • Andrew

    Hi, I asked this previously but have still not have a response:

    As soon as I add html for the text input to functions.php it breaks my site. I know you suggest it could be used as a plug-in, but I need it in my theme file.

    Please can you help by showing how to do this? It would be really appreciated. Thanks.

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      Broke your site how?

      Error message? Are you sure you didn’t just mistype something?

      • Andrew

        Hi, thanks for the reply.

        Yes, I actually just cut and pasted into functions.php

        I got an error message.

      • Andrew

        Is there any chance of a reply to this please?

  • Guillaume

    Very nice post, WP-tuts+ rocks. For the meta-box, I personally used this library which is very well done:

    http://www.deluxeblogtips.com/p/meta-box-script-for-wordpress.html

    Cheers

  • Alan

    Any chance you could show us how to deal with file uploads sometime?

    I was actually wanting to implement a gallery of sorts. Whereby the custom post type would have an unfixed amount of images associated with the post. I image the user being able to upload an image and then click something like ‘Upload Another’ to show another image upload on the post form. Does that make sense?

    Great tut by the way thanks Chris

    • http://www.christopherguitar.net/wordpress/ Chris
      Author

      Alan,

      There will be a “part 2″ of this tutorial with some practical examples. It will include getting the thickbox uploader working for this.

      That said, if you want to create a gallery post, you might be better off using (or overriding) the default [gallery] shortcode.

      -CD

  • Thomas

    Is there a way to add a rich text editor field to a custom meta box?

  • http://tutspress.com TutsPress

    Nice one! Thanks for the tutorial.

  • http://jarida234.com Sani Aliyu

    Great Tutorial! I have to say you guys do a very good job of making everything seem so easy and effortless. I am going to ‘get my hands dirty’ starting now with this tutorial. Great work!

  • http://isotrope.net isotrope

    How would you make the dropdown be based on another Custom Post Type?
    Say you have a Movies custom post type and a Directors cpt. How would you make a select field with the options generated based on the Directors posts?
    BTW, thanks for the great tute!

  • Pingback: Three Uses for Custom WordPress Meta Boxes | Wptuts+

  • http://thinkdobecreate.com Stephanie

    I’ve been using a similar set-up, but had been lacking some of the validation methods you provide here.

    The “selected” and “checked” functions will clean-up my code a lot!

  • Pingback: holyswisscheese / Wordpress: Useful links, July

  • Pingback: L’Hebdo WordPress : | Choisir-son-CMS.tk

  • http://www.webstudions.be Nick Scheynen

    Hi Chris,

    Nice tutorial, I really wanted to know how all this worked. However I can’t seem to echo the custom fields on my page using:

    if( get_post_meta( $post->ID, ‘my_meta_box_text’, true ) )
    {
    echo get_post_meta( $post->ID, ‘my_meta_box_text, true ) );
    }

    as you suggested. Now I checked the codex and the only way I manage to echo the text is this way:

    $custom_fields = get_post_custom($post_id);
    $text = $custom_fields['my_meta_box_text'];
    foreach ( $my_custom_field as $key => $value )
    $text = $value;
    echo $value;

    This seems somewhat to difficult to do something easy, but I can’t find a working alternative. Does anybody have an idea? (I’m just using this code inside twentyeleven.)

  • Pingback: L’Hebdo WordPress : WordPress 3.3 – BuddyPress 1.5 – Astuces | Choisir-son-CMS.tk

  • Pingback: 10 Advanced Wordpress Theme Development Tutorials | Wordpress MetaBlog

  • Andrew

    I am sick and tired of seeing questions (from other and myself, see repeated requests for help above) ignored.

    I am paying a monthly fee and wonder whether you value this subscription?

    I ask again, would you please respond to requests for help?

    Thank you.

  • Pingback: 10 Advanced Wordpress Theme Development Tutorials | Tessa Explains How to Do Things

  • Lucas Costa

    Greatest article! A doubt: if you are applying ‘esc_attr’ in saving the data, why would you apply it again when using it?

  • http://www.shaunmbrown.com/ Shaun

    Great tut!
    Curious, if I were to create more meta boxes, must I repeat this entire block of code each time and alter it to my needs or is there a less bloated way of doing that?

    • http://www.shaunmbrown.com/ Shaun

      Sorry, one last question –
      I see you refer us to use get_post_meta or get_post_custom functions to output the data into our templates, however I took a look at the codex and Im still pretty confused…

      Would it be possible to give a short example of how to port this data into our templates?

      For example: I changed your code to suite my needs to display a product price in a specific place in the template, I just need to know the correct template tag to be used to output that data from my custom post type, id youd be so kind! :)

      Best,
      SB

  • http://www.kiubmen.com Kiubmen

    As I can show the checkbox value in columns in the page manager.
    I’ve tried the following code but the column is empty.
    Please some help.

    add_filter(‘manage_pages_columns’, ‘add_destacado_column’);
    add_action(‘manage_pages_custom_column’, ‘echo_destacado_column’, 10, 2);

    function add_destacado_column($columns) {
    $columns['destacado'] = ‘Destacado’;
    return $columns;
    }

    function echo_destacado_column($column, $id) {
    if (‘destacado’ == $column)
    echo get_post_meta($post->ID, ‘_my_meta_box_check’, true);
    }
    ?>

  • http://themeforest.net/item/transforms-html-template/409454 Fahim

    Please Help me

    i change the position of the meta box i want to use it on the page not on the post

    i create a template page and then use the following code to grab the values from the box

    ID );
    $text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ”;
    $selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'][0] ) : ”;
    $check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'][0] ) : ”;
    wp_nonce_field( ‘my_meta_box_nonce’, ‘meta_box_nonce’ );

    ?>

    but this code only work on my singpost page not on the page if i put the value from a post it show but when i put the values from a page it not work

    Please help me

  • Ryan

    There are loads of tutorials out there that attempt to cover this very subject, and I’m amazed at how many are crappy. Yours works, out of the box. Thanks a million for the comprehensive write-up.

  • Pingback: WordPress: Useful links, July / Holy Swiss Cheese

  • nacho

    hi! i’m newbie in wordpress, what about ordering post by meta-box? For example I’ve a meta-box called price, and i want to order items( custom post type) by price.. : S ?

  • Pingback: How to Build a Shortened URL Service with WordPress Custom Post Type | Wptuts+

  • Gavin

    A clear and useful tutorial. However, I’m having a problem with saving fields. I have multiple text fields but when I click Publish or Update, all entries into those different fields change to the last field values. For example:

    Name: Jo Bloggs
    Address: An address
    Phone: A phone number
    Website: A website

    … all change to …

    Name: A website
    Address: A website
    Phone: A website
    Website: A website

    The code is:

    add_action(‘add_meta_boxes’, ‘listings_add’);
    function listings_add() {
    add_meta_box(‘listings_box’, ‘Listings’, ‘listings_cb’, ‘post’, ‘normal’, ‘high’);
    }
    function listings_cb( $post ) {
    $values = get_post_custom( $post->ID);
    $text = isset( $values['name'] ) ? esc_attr( $values['name'][0] ) : ”;
    $text = isset( $values['address'] ) ? esc_attr( $values['address'][0] ) : ”;
    $text = isset( $values['phone'] ) ? esc_attr( $values['phone'][0] ) : ”;
    $text = isset( $values['website'] ) ? esc_attr( $values['website'][0] ) : ”;

    wp_nonce_field( ‘listings_nonce’, ‘meta_box_nonce’ );
    ?>

    Name
    <input type="text" name="name" id="name" value="” />

    Address
    <input type="text" name="address" id="address" value="” />

    Phone
    <input type="text" name="phone" id="phone" value="” />

    Website
    <input type="text" name="website" id="website" value="” />

    array( // on allow a tags
    ‘href’ => array() // and those anchords can only have href attribute
    )
    );

    // Probably a good idea to make sure your data is set
    if( isset( $_POST['name'] ) )
    update_post_meta( $post_id, ‘name’, wp_kses( $_POST['name'], $allowed ) );
    if( isset( $_POST['address'] ) )
    update_post_meta( $post_id, ‘address’, wp_kses( $_POST['address'], $allowed ) );
    if( isset( $_POST['phone'] ) )
    update_post_meta( $post_id, ‘phone’, wp_kses( $_POST['phone'], $allowed ) );
    if( isset( $_POST['website'] ) )
    update_post_meta( $post_id, ‘website’, wp_kses( $_POST['website'], $allowed ) );

    }

    Evidently I’m doing something wrong.

  • Gavin

    I’ve put the above code into pastie.

    http://pastie.org/2465091

  • Gavin

    Sorted it, I had to have different variables (still new to all this) rather than all being $text. Thanks again for the great tutorial.

  • Alessio

    My select and checkbox fields won’t save… why?
    I’ve made copy/paste from your code.

    I have this issue with following another tutorial about meta-box …. what can it be the problem?

  • Alessio

    If I want to associate a meta-box to Custom Post Type, instead of $post what I’ve to write $custom_post_name ?

  • EmpreJorge

    Hi, nice tut, very helpful.
    One question, is there any way to have the checkbox “checked” by default???
    thanks.

    • EmpreJorge

      I’ve solved it :D
      <?php if(empty($check)){echo ‘checked=”checked”‘;} else{checked( $check, ‘on’ );} ?>

  • priyanshu

    he grt stuff but wht if , if i want to add file upload filed here i mean how can i add file type field and to store its name….

  • Pingback: WordPress Database: Converting Category ID to Category Slugs | Wptuts+

  • Pingback: My Stream » Gettin’ Jiggy wit’ the WP Database: Converting Category Slugs to IDs ($wpdb)

  • Pingback: Iterate through an image gallery in my template | SeekPHP.com

  • Bo

    I have one question, i used this good tutorial for only textboxes, but when i have saved the post, the values in the metaboxes a dissapearing, shouldn’t they be int the boxes so i can update them and se them?

  • Pingback: Attaching Files To Posts Using WordPress Custom Meta Boxes | Wptuts+

  • Pingback: Three Practical Uses for Custom Meta Boxes | kabayview.com

  • Mihael

    I never took the time to say thanks, so… Thanks for this tutorial :)

  • http://www.jeremypass.com Jeremy Pass

    I have two drop-downs…but neither retain their value after publishing, then returning to edit…

    Any ideas? Here is the code I am using…

    here is my code…
    http://pastie.org/2765659

    Thanks!
    Jeremy

  • http://www.jeremypass.com Jeremy Pass

    Hey there, I have two drop-downs…but neither retain their value after publishing, then returning to edit…

    Any ideas? Here is the code I am using…
    http://pastie.org/2765659

    Thanks!
    Jeremy

  • http://8mediaeg.com 8MEDIA

    i have use custom boxes in more than one site ,, i was looking for some thing which i could use to make my custom fields appear automatic an now i get it ,, so thanks very much :D

  • http://wplancer.com Banago

    You can also use the selected() function with radio buttons.

    You’re wrong here – you can use the checked() function with radio actually – selected won’t work.

  • SoYoung

    Very Useful! Thank you ^^

  • Pingback: Custom admin post.php page | SeekPHP.com

  • Pingback: How to Create Custom WordPress Write/Meta Boxes | Wptuts+

  • Pingback: Automagic Thumbnail & Image Management | Wptuts+

  • Pingback: My Stream » Automagic Post Thumbnails & Image Management

  • Pingback: Automagic Post Thumbnails & Image Management | Graphfucker

  • Pingback: Reusable Custom Meta Boxes Part 1: Intro and Basic Fields | Wptuts+

  • Pingback: My Stream » Reusable Custom Meta Boxes Part 1: Intro and Basic Fields

  • Pingback: Reusable Custom Meta Boxes Part 1: Intro and Basic Fields | Graphfucker

  • Pingback: Автоматическое управление картинками в постах на WordPress | Wordpresso

  • http://www.welancers.com Aslam Doctor

    Damn this one was so useful to me. Thank you Christopher & WPTuts :)

  • Adam

    Fantastic tutorial. I’d been using the WP codex for it, but this cleared up a few omissions very nicely. Thank you so much for posting!

  • Pingback: Segnalibri al 13 gennaio 2012 | Ubuntu block notes

  • Thomas

    Most excellent tutorial! Very useful. Thank you!

  • http://pixeltuner.de/ Jonathan

    Thank you for this guide!

    But unfortunately one question still remains unanswered:
    My self-created Meta Box should be positioned above the Publish-Metabox, without drag and drop.
    How can I position my self-created Meta Box in the right column above the Publish-Metabox?

    Do you know what I mean?
    Many thanks in advance!

  • Pingback: Learning Code – Week 2 Adding Custom Wordpress Meta Boxes | Marketer Matt

  • http://www.ianhoar.com Ian

    Thanks for the great post, just made my current project a lot more user friendly.

  • http://- CPNV

    Thanks for this school lesson ….

  • Salih

    Hey…this is awsome, and I have already implemented this technique. now i got a situation where I want to validate the data, that exists in database or not. for eg: I am using a custom meta box named as ‘FILE NO’ what i want is before saving a post there should be a validation on if the FILE NO already exists or not, if it is it should produce an error msg and inform the editor/admin, I hope someone will help me…. thank u

  • http://www.tech-plazaa.com fahim

    Please Help me i am unable to retrieve the check box value true or false , how i put the condition in template file to know user check or unchecked it

    I am new Please some body help

  • Dan

    Nice tutorial! a bit disappointing when the fields reset in the back end on save.
    The updated source file helped, thanks Chris.

  • Pingback: Custom Meta Fields for a Chosen Post Format in WordPress | Ash Robbins

  • david

    Hi,
    thanks!
    It works great with one checkbox, but how to do to save multiples checkbox ?

  • Pingback: How to Use Custom Sidebars on Posts and Pages | How to Web

  • Pingback: How to Use Custom Sidebars on Posts and Pages | Wptuts+

  • Pingback: How to Make a Radio Station Schedule Using WordPress | Wptuts+

  • Pingback: How to Make a Radio Station Schedule Using WordPress | Wordpress Webdesigner

  • Pingback: How to Make a Radio Station Schedule Using WordPress | Shadowtek Hosting and Design Solutions

  • Pingback: My Stream | How to Make a Radio Station Schedule Using WordPress | My Stream

  • Pingback: How to Make a Radio Station Schedule Using WordPress | How to Web

  • Pingback: Wordpress Leaks » How to Make a Radio Station Schedule Using WordPress

  • AndyiBM

    Thanks for this… really useful, and slightly easier to follow than other tuts out there.

    Also, I too found the downloaded source file more reliable than the code in the post, which still seemed to have errors.

    Cheers.

  • Tavo

    I get a white screen when i hit the update button.. what did i do wrong?

    • Andres Santillan

      make sure you don’t have a function twice, I had the same problem until i moved the whole site locally and got the error saying that I was duplicating a class.

  • Design1

    Thanks for this tutorial! Saved my time!!

  • Pingback: 31st » Ressources WordPress ( cms, plugins… )

  • NK

    this tutorial is perfect and exactly what i was was looking- all i need is one simple thing:

    one line of code to display the meta box beneath the post content on the homepage. any help please?

    i need to display the meta box content on the front end and adding

    yields a fatal error when adding to index.php or single.php. the metabox works perfectly in the dashboard, retains the saved input, etc, but what do i add so it’s actually visible on the front end?

    i’m a designer and not a programmer so thanks in advance.

  • Pingback: 10 Advanced Wordpress Theme Development Tutorials | This is Not The Future

  • Pingback: How to Create Custom WordPress Write/Meta Boxes | 12-cms

  • http://www.theextremewebdesigns.com Robert

    Hi Chris,
    Awesome tutorial! But I must say, a very important part of the “correct” code that is still left out from the tutorial’s code is the code that you have posted on July 19, 2011 at 6:29 pm. Without using the code that you posted on the above mentioned datr, it’s not possible to populate the fields value, the checkbox checked value & the select dropdown selected value, once the post is saved. So it would really help if you can update the actual tutorial code with the revised code. For others who are confused, use the following complete cd_meta_box_cb function:

    function cd_meta_box_cb( $post )
    {
    // $post is already set, and contains an object: the WordPress post
    global $post;

    $values = get_post_custom( $post->ID );
    $text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ”;
    $selected = isset( $values['my_meta_box_select'] ) ? esc_attr( $values['my_meta_box_select'][0] ) : ”;
    $check = isset( $values['my_meta_box_check'] ) ? esc_attr( $values['my_meta_box_check'][0] ) : ”;

    // We’ll use this nonce field later on when saving.
    wp_nonce_field( ‘my_meta_box_nonce’, ‘meta_box_nonce’ );
    ?>

    Text Label
    <input type="text" name="my_meta_box_text" id="my_meta_box_text" value="” />

    Color

    <option value="red" >Red
    <option value="blue" >Blue

    <input type="checkbox" id="my_meta_box_check" name="my_meta_box_check" />
    Do not check this

    <?php
    }

    There is 1 more correction. For the code that you have provided in the tutorial for the checkbox, you are missing $post_id in the function arguments. So anyone trying to copy the code off of that function will experience issues with the code. So you might want to change it from :

    function cd_meta_box_cb()
    to
    function cd_meta_box_cb( $post )

    But all in all, it’s an excellent tutorial that I have seen & I am sure it has helped many of us learn about how things work. So I appreciate you for all the time & effort you have spent in sharing your knowledge with all of us.

    • Peter P

      Hi, would you please send me a link to your code in pastebin I think it didn’t render correctly as a comment and I’d like to update my code so the values are shown when editing a post. Thanks

  • Pingback: Building a Simple Announcements Plugin for WordPress | Wptuts+

  • Pingback: Building a Simple Announcements Plugin for WordPress | Wordpress Webdesigner

  • Pingback: My Stream | Building a Simple Announcements Plugin for WordPress | My Stream

  • http://www.smartsolutionpro.info/ Ahmad

    <input type="checkbox" id="my_meta_box_check" name="my_meta_box_check" />

    put this code if you want to get checked the check box without the text box and radio button.

  • http://sma Ahmad

    $value = get_post_meta( $post->ID,’my_meta_box_check’,true );
    <input type="checkbox" id="my_meta_box_check" name="my_meta_box_check" />

    use this code to work alone with checkbox.

  • Pingback: Wordpress Leaks » Building a Simple Announcements Plugin for WordPress

  • http://twitter.com/mtoppa Michael Toppa

    If you are taking the input from the meta box and adding it to an existing array, you’ll want to make sure you retrieve the array that’s attached to the published post, as WordPress saves draft revisions with separate IDs. Like this:

    if ($parent_id = wp_is_post_revision($post_id)) {
    $your_meta_array = get_post_meta($parent_id, ‘your_meta_array’, true);
    }
    else {
    $your_meta_array = get_post_meta($post_id, ‘your_meta_array’, true);
    }

    Also, WordPress kindly serialized and unserialized arrays for you when you save them this way.

  • Pingback: Handling WordPress meta data and post revisions | Nothing But Words

  • Pingback: 使用jquery插件创建一个简单的wordpress通知插件 | iluther-专注web技术

  • http://www.php-sri-lanka.com/ Upeksha Wisidagama

    Good Tut. Clearly explains the basics of custom meta boxes. Thanks!

  • http://www.facebook.com/androidgamezone.pp.ua Dry GameZone

    somebody help me please

    add_action( ‘add_meta_boxes’, ‘meta_games_function_add’ );
    function meta_games_function_add()
    {
    add_meta_box( ‘meta-games’, ‘Параметры игры’, ‘meta_games_function’, ‘agz_games’, ‘normal’, ‘high’ );
    }

    function meta_games_function($post)
    {
    $values = get_post_custom( $post->ID );
    $manufacter = isset( $values['manufacter'] ) ? esc_attr( $values['manufacter'][0] ) : ”;
    ?>
    Разработчик
    <input type="text" name="manufacter" id="manufacter" value="” />
    array( // on allow a tags
    ‘href’ => array() // and those anchors can only have href attribute
    )
    );
    // Make sure your data is set before trying to save it
    if( isset( $_POST['manufacter'] ) )
    update_post_meta( $post_id, ‘manufacter’, wp_kses( $_POST['manufacter'], $allowed ) );

    }

    don’t save/or save but dont show me my “manufacter” variable

    Help please. What i miss?

  • Pingback: Utilizing Custom Fields to Create Review Boxes | Wptuts+

  • Pingback: Utilizing Custom Fields to Create Review Boxes | Wordpress Webdesigner

  • Pingback: Utilizing Custom Fields to Create Review Boxes | Wordpress Leaks

  • WallaceErick

    How to display only the value on the theme?
    After option selected…

  • http://zaf.web.id/ Ahmad Zafrullah

    awesome, great tutorial :)

  • Pingback: Используем кастомные поля для создания мета-блоков с обзорами | Wordpresso

  • Pingback: Create wordpress meta box « dineshshrivastava

  • http://twitter.com/noelmcglinchey Noel McGlinchey

    Hi, the line in the function cd_meta_box save:

    // if our current user can’t edit this post, bail
    if( !current_user_can( ‘edit_post’ ) ) return;

    should be:

    if( !current_user_can( ‘edit_post’, $post_id ) ) return;

    prevents undefined offset notice and cannot modify header warning.

    Cheers for the tutorial!

  • Bibbins

    Hi,

    Cheers for the great tutorial, it’s very easy to follow and really helpful!

    I was wondering if anyone could explain something about a line of code that uses the ? operator. The code is:

    $text = isset( $values['my_meta_box_text'] ) ? esc_attr( $values['my_meta_box_text'][0] ) : ”;

    I understand what happens if the expression evaluates to TRUE (i.e. if the meta text box has a value), but I can’t understand what happens if the expression evaluates to FALSE. The code after the colon that would be triggered in this scenario is merely: ” (i.e. nothing but a closing curly quote). I would really appreciate it if someone could explain what this code does or what it refers to?! Cheers for any help.

  • http://www.facebook.com/king.of.kerker Lin Ti-Wen

    you deserve a Nobel Prize on this

    • http://www.facebook.com/king.of.kerker Lin Ti-Wen

      dude, I figured this out…. you’ll have to remove the last php closing bracket (?>) in your functions.php to make it works…

  • http://twitter.com/IJNanayakkara Isuru Nanayakkara

    What is meta_box_nonce and in the Step 3 Saving the Data section, the second code snippet line #9? I don’t see it declared above. Can you please explain what it does? Basically what is a nonce?