Add A Meta Box In WordPress

Posted on 24. Aug, 2009 by in Theme Options Page

Creating the options pages is something we’ve touched upon previously here on WPShout, and whilst developing my soon-to-be-released WordPress theme, Biblioteca, I wanted to add some options to the post writing page, and in this post I’m going to be sharing how I did it.

in-post-download

How the in-post options work

Basically, we’re going to be adding some boxes to the post and page writing pages that give our users a number of options, including customising the <title> tag, the meta description and the URL of a featured image:

These options get displayed immediately below the post/page writing area, and the user can enter text. This text, when the post is saved gets saved as custom fields. For example, on this post I’ll enter some text “Hello. This is a test.”  in the “Image” field. The results are below:

So that proves it works! Let’s get straight into implementing it. First off, all credits go to Justin Tadlock – code comes more or less straight out of Hybrid.

Making the in post options

The first thing you need to do in order to make your own in post options is to open up your functions.php file. This is the file that gives you a lot of power, but can also totally wreck your theme – power comes with responsibility! Always have a backup readily to hand.

The first code to add is the following, which does the job of adding the box to the admin menu:

<?php
/**
Made with the help of a tutorial at WPShout.com => http://wpshout.com.

Courtesy of the Hybrid theme - themehybrid.com

/* Add a new meta box to the admin menu. */
	add_action( 'admin_menu', 'hybrid_create_meta_box' );

/* Saves the meta box data. */
	add_action( 'save_post', 'hybrid_save_meta_data' );

/**
 * Function for adding meta boxes to the admin.
 * Separate the post and page meta boxes.

function hybrid_create_meta_box() {
	global $theme_name;

	add_meta_box( 'post-meta-boxes', __('Post options'), 'post_meta_boxes', 'post', 'normal', 'high' );
	add_meta_box( 'page-meta-boxes', __('Post options'), 'page_meta_boxes', 'page', 'normal', 'high' );
}

With that added, the next step is to start an array which will be the text used by the options page. The ‘name’ is the name of the custom field that will be generated by the options. Next is the text displayed on the right and finally the ‘type’ is what type of box the theme is to display; either the large textarea or the smaller single line text:

function hybrid_post_meta_boxes() {

	/* Array of the meta box options. */
	$meta_boxes = array(
		'title' => array( 'name' => 'Title', 'title' => __('Title', 'hybrid'), 'type' => 'text' ),
		'description' => array( 'name' => 'Description', 'title' => __('Description', 'hybrid'), 'type' => 'textarea' ),
		'image' => array( 'name' => 'Image', 'title' => __('Image:', 'hybrid'), 'type' => 'text' ),
		'featured' => array( 'name' => 'Featured', 'title' => __('Featured img:', 'hybrid'), 'type' => 'text' ),

	);

	return apply_filters( 'hybrid_post_meta_boxes', $meta_boxes );
}

You’ll notice the last bit of code is for pages only, where no featured image option is added.

Next, the code that displays the boxes and formats them:

function post_meta_boxes() {
	global $post;
	$meta_boxes = hybrid_post_meta_boxes(); ?>

	<table class="form-table">
	<?php foreach ( $meta_boxes as $meta ) :

		$value = get_post_meta( $post->ID, $meta['name'], true );

		if ( $meta['type'] == 'text' )
			get_meta_text_input( $meta, $value );
		elseif ( $meta['type'] == 'textarea' )
			get_meta_textarea( $meta, $value );
		elseif ( $meta['type'] == 'select' )
			get_meta_select( $meta, $value );

	endforeach; ?>
	</table>
<?php
}

/**
 * Displays meta boxes on the Write Page panel.  Loops
 * through each meta box in the $meta_boxes variable.
 * Gets array from hybrid_page_meta_boxes()
 *
 * @since 0.3
 */
function page_meta_boxes() {
	global $post;
	$meta_boxes = hybrid_page_meta_boxes(); ?>

	<table class="form-table">
	<?php foreach ( $meta_boxes as $meta ) :

		$value = stripslashes( get_post_meta( $post->ID, $meta['name'], true ) );

		if ( $meta['type'] == 'text' )
			get_meta_text_input( $meta, $value );
		elseif ( $meta['type'] == 'textarea' )
			get_meta_textarea( $meta, $value );
		elseif ( $meta['type'] == 'select' )
			get_meta_select( $meta, $value );

	endforeach; ?>
	</table>
<?php
}

/**
 * Outputs a text input box with arguments from the
 * parameters.  Used for both the post/page meta boxes.
 *
 * @since 0.3
 * @param array $args
 * @param array string|bool $value
 */
function get_meta_text_input( $args = array(), $value = false ) {

	extract( $args ); ?>

	<tr>
		<th style="width:10%;">
			<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
		</th>
		<td>
			<input type="text" name="<?php echo $name; ?>" id="<?php echo $name; ?>" value="<?php echo wp_specialchars( $value, 1 ); ?>" size="30" tabindex="30" style="width: 97%;" />
			<input type="hidden" name="<?php echo $name; ?>_noncename" id="<?php echo $name; ?>_noncename" value="<?php echo wp_create_nonce( plugin_basename( __FILE__ ) ); ?>" />
		</td>
	</tr>
	<?php
}

/**
 * Outputs a select box with arguments from the
 * parameters.  Used for both the post/page meta boxes.
 *
 * @since 0.3
 * @param array $args
 * @param array string|bool $value
 */
function get_meta_select( $args = array(), $value = false ) {

	extract( $args ); ?>

	<tr>
		<th style="width:10%;">
			<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
		</th>
		<td>
			<select name="<?php echo $name; ?>" id="<?php echo $name; ?>">
			<?php foreach ( $options as $option ) : ?>
				<option <?php if ( htmlentities( $value, ENT_QUOTES ) == $option ) echo ' selected="selected"'; ?>>
					<?php echo $option; ?>
				</option>
			<?php endforeach; ?>
			</select>
			<input type="hidden" name="<?php echo $name; ?>_noncename" id="<?php echo $name; ?>_noncename" value="<?php echo wp_create_nonce( plugin_basename( __FILE__ ) ); ?>" />
		</td>
	</tr>
	<?php
}

/**
 * Outputs a textarea with arguments from the
 * parameters.  Used for both the post/page meta boxes.
 *
 * @since 0.3
 * @param array $args
 * @param array string|bool $value
 */
function get_meta_textarea( $args = array(), $value = false ) {

	extract( $args ); ?>

	<tr>
		<th style="width:10%;">
			<label for="<?php echo $name; ?>"><?php echo $title; ?></label>
		</th>
		<td>
			<textarea name="<?php echo $name; ?>" id="<?php echo $name; ?>" cols="60" rows="4" tabindex="30" style="width: 97%;"><?php echo wp_specialchars( $value, 1 ); ?></textarea>
			<input type="hidden" name="<?php echo $name; ?>_noncename" id="<?php echo $name; ?>_noncename" value="<?php echo wp_create_nonce( plugin_basename( __FILE__ ) ); ?>" />
		</td>
	</tr>
	<?php
}

And finally, saving the options entered as custom fields:

/**
 * Loops through each meta box's set of variables.
 * Saves them to the database as custom fields.
 *
 * @since 0.3
 * @param int $post_id
 */
function hybrid_save_meta_data( $post_id ) {
	global $post;

	if ( 'page' == $_POST['post_type'] )
		$meta_boxes = array_merge( hybrid_page_meta_boxes() );
	else
		$meta_boxes = array_merge( hybrid_post_meta_boxes() );

	foreach ( $meta_boxes as $meta_box ) :

		if ( !wp_verify_nonce( $_POST[$meta_box['name'] . '_noncename'], plugin_basename( __FILE__ ) ) )
			return $post_id;

		if ( 'page' == $_POST['post_type'] && !current_user_can( 'edit_page', $post_id ) )
			return $post_id;

		elseif ( 'post' == $_POST['post_type'] && !current_user_can( 'edit_post', $post_id ) )
			return $post_id;

		$data = stripslashes( $_POST[$meta_box['name']] );

		if ( get_post_meta( $post_id, $meta_box['name'] ) == '' )
			add_post_meta( $post_id, $meta_box['name'], $data, true );

		elseif ( $data != get_post_meta( $post_id, $meta_box['name'], true ) )
			update_post_meta( $post_id, $meta_box['name'], $data );

		elseif ( $data == '' )
			delete_post_meta( $post_id, $meta_box['name'], get_post_meta( $post_id, $meta_box['name'], true ) );

	endforeach;
}
?>

And we’re done creating the options! Next, we’re going to be implementing these options.

Giving the user the option to change the title tag without a plugin

The first field/option we offered was “Title”. Obviously we’re going to use this as the <title> tag for our post. How? As you may recall, the text input into the boxes gets spitted out as a custom field, so we can display the “Title” as the title tag with the following (open up the header.php):

<title><?php echo get_post_meta($post->ID, "Title", true); ?></title>

But that would be a seriously bad idea. What if it’s the homepage?! What if there is no custom field?! The folllowing is much better; it should be used in conjunction with your current SEO’d setup, will only display on posts and pages and has an option for if no custom field exists:

<?php if ( is_single() || is_page() ) { ?><?php $title = get_post_meta($post->ID, 'Title', true);  if ($title) { ?>
<?php echo get_post_meta($post->ID, "Title", true); ?> | <?php bloginfo('name'); ?>
<?php } else { ?>
<?php wp_title(''); ?> | <?php bloginfo('name'); ?>
<?php } ?>
<?php } ?>

Giving the user the option to change the meta description without a plugin

The second field was ‘Description’. This is your meta description, an important part of your SEO strategy. Similar code to the above will display the content of the box, but with a fall back for if no custom field exists:

lt;?php if (is_single() || is_page() ) : if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<meta name="description" content="<?php $description = get_post_meta($post->ID, 'Description', true);  if ($description) { ?><?php echo get_post_meta($post->ID, "Description", true); ?>
<?php } else { ?><?php the_excerpt_rss(); ?><?php } ?>" />
<?php endwhile; endif; elseif(is_home()) : ?>
<meta name="description" content="<?php bloginfo('description'); ?>" />
<?php endif; ?>

Displaying images

The final field was the URL for a ‘featured’ image. We can integrate this into our WordPress theme with the following:

<?php $postimageurl = get_post_meta($post->ID, 'Image', true); if ($postimageurl) { ?>
<img src="<?php bloginfo('template_url'); ?>/scripts/timthumb.php?src=<?php echo get_post_meta($post->ID, "Image", true); ?>&h=250&w=250&zc=1" alt=""> 
<?php }else { ?> 
<img src="<?php bloginfo('template_url'); ?>/images/noimage.jpg" alt="No image available" />
<?php } ?>

Concluding

With that, we’re finished creating our in post options! The download for the code is available at the top of the post. This is a brilliant, simple and effective way to improve your WordPress theme.

If you have enjoyed this post, please take a second to save it to your favourite social bookmarking site with the links below and even subscribe by RSS or follow me on Twitter! Any questions, suggestions or queries, please do leave a comment.

Tags: ,

Follow on Twitter! Subscribe!

WPShout is hosted by the fine folks at WPWebHost.

You can get exactly the same hosting as WPShout has for $7.95/month with WPWebHost's Freedom Plan.

Plus get 30% off the Freedom Plan with the code WPSHOUT.

Visit WPWebHost

Alex's Gravatar

Alex Denning is the founder of WPShout. A WordPress developer from London, Alex is a keen musician and freelance writer and developer.

You can find Alex on Twitter.

45 Responses to “Add A Meta Box In WordPress”

  1. Comment Guidelines Violation 3

    25. Aug, 2009

    Wow! this is very nice tips for modify WordPress feature. Thank you so much!

    Reply to this comment
  2. Akshay

    26. Aug, 2009

    the meta description code looks wrong it display the title, pls check it out.

    Also correct the second code of the title(remove lt; & >)
    .-= Akshay´s last blog ..URL Upload Script =-.

    Reply to this comment
    • Alex Denning

      26. Aug, 2009

      Thanks for the heads up. Some idiot (erm..) copied the wrong code.

      Reply to this comment
  3. Epic Alex

    28. Aug, 2009

    Thanks for talking us through this Alex, simplifying the use of custom fields for clients is something I’ve been looking into doing for a while. I’d never looked into the hybrid theme before, but it seems like it’s a good place to learn some awesome code!

    Do you know though whether it’s possible to make the field for the images an upload field, essentially cutting out a step in the process?
    .-= Epic Alex´s last blog ..Site Redesign Now Live =-.

    Reply to this comment
    • Alex Denning

      30. Aug, 2009

      I’m not aware of being able to add something like that straight into the image uploading panel (you could… *horror* hack the backend…), but another way to do it would be to auto grab the image – something like:

      // Get URL of first image in a post
      function catch_that_image() {
      global $post, $posts;
      $first_img = '';
      ob_start();
      ob_end_clean();
      $output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
      $first_img = $matches [1] [0];

      // no image found display default image instead
      if(empty($first_img)){
      $first_img = "/images/default.jpg";
      }
      return $first_img;
      }

      With that in the functions.php file and then grab the image with:

      <img src="<?php echo catch_that_image() ?>" alt=""/>

      Reply to this comment
  4. Super, I was waiting for this function.
    .-= Shabu | WordPress Daddy´s last blog ..A Beginner’s Guide To WordPress Theme Development =-.

    Reply to this comment
  5. Brian

    28. Oct, 2009

    Hi Alex,

    I love the tutorial, opens up many possibilities within the CMS.

    However, when I copy and paste your code into my functions file it works a treat, but when I change the names of the meta boxes in the array they are not saved as custom fields. Everything shows up as it should on screen in the ‘write page’ area, but on save nothing happens.

    Any ideas?

    Here is an example of one line – ‘header paragraph’ => array( ‘name’ => ‘Header Paragraph’, ‘title’ => __(‘Header Paragraph’, ‘hybrid’), ‘type’ => ‘text’ ),

    Many thanks,

    Brian

    Reply to this comment
    • Alex Denning

      29. Oct, 2009

      Could you paste the whole code you copied? You’ll need to wrap it with <code><pre>CODE HERE</code></pre> and encode the HTML with –> http://www.opinionatedgeek.com/dotnet/tools/htmlencode/Encode.aspx

      Reply to this comment
      • David M Sawyer

        31. Oct, 2009

        I have a similar issue. Interestingly I did a test before changing it and that did create the custom field and save it. However once I changed the names it would not save any changes (but did show changes if I put the change directly in the custom field. I only changed $meta_boxes array sections.
        I’m excited to use this in my projects, it is so much better than the default custom field usage!

        http://wpshout.com.

        Courtesy of the Hybrid theme - themehybrid.com

        * Adds the Hybrid Settings meta box on the Write Post/Page screeens
        *
        * @package Hybrid
        * @subpackage Admin
        */

        /* Add a new meta box to the admin menu. */
        add_action( 'admin_menu', 'hybrid_create_meta_box' );

        /* Saves the meta box data. */
        add_action( 'save_post', 'hybrid_save_meta_data' );

        /**
        * Function for adding meta boxes to the admin.
        * Separate the post and page meta boxes.
        *
        * @since 0.3
        */
        function hybrid_create_meta_box() {
        global $theme_name;

        add_meta_box( 'post-meta-boxes', __('Post options'), 'post_meta_boxes', 'post', 'normal', 'high' );
        add_meta_box( 'page-meta-boxes', __('Post options'), 'page_meta_boxes', 'page', 'normal', 'high' );
        }

        /**
        * Array of variables for post meta boxes. Make the
        * function filterable to add options through child themes.
        *
        * @since 0.3
        * @return array $meta_boxes
        */
        function hybrid_post_meta_boxes() {

        /* Array of the meta box options. */
        $meta_boxes = array(
        'main_verse' => array( 'name' => 'Main verse', 'title' => __('Main verse', 'hybrid'), 'type' => 'text' ),
        'other_verses' => array( 'name' => 'Other verses', 'title' => __('Other verses', 'hybrid'), 'type' => 'text' ),
        'image' => array( 'name' => 'Image', 'title' => __('Image:', 'hybrid'), 'type' => 'text' ),
        'featured' => array( 'name' => 'Featured', 'title' => __('Featured img:', 'hybrid'), 'type' => 'text' ),

        );

        return apply_filters( 'hybrid_post_meta_boxes', $meta_boxes );
        }

        /**
        * Array of variables for page meta boxes. Make the
        * function filterable to add options through child themes.
        *
        * @since 0.3
        * @return array $meta_boxes
        */
        function hybrid_page_meta_boxes() {

        /* Array of the meta box options. */
        $meta_boxes = array(
        'main_verse' => array( 'name' => 'Main verse', 'title' => __('Main verse', 'hybrid'), 'type' => 'text' ),
        'other_verses' => array( 'name' => 'Description', 'title' => __('Other verses', 'hybrid'), 'type' => 'text' ),

        );

        return apply_filters( 'hybrid_page_meta_boxes', $meta_boxes );
        }

        /**
        * Displays meta boxes on the Write Post panel. Loops
        * through each meta box in the $meta_boxes variable.
        * Gets array from hybrid_post_meta_boxes().
        *
        * @since 0.3
        */
        function post_meta_boxes() {
        global $post;
        $meta_boxes = hybrid_post_meta_boxes(); ?>

        ID, $meta['name'], true );

        if ( $meta['type'] == 'text' )
        get_meta_text_input( $meta, $value );
        elseif ( $meta['type'] == 'textarea' )
        get_meta_textarea( $meta, $value );
        elseif ( $meta['type'] == 'select' )
        get_meta_select( $meta, $value );

        endforeach; ?>

        ID, $meta['name'], true ) );

        if ( $meta['type'] == 'text' )
        get_meta_text_input( $meta, $value );
        elseif ( $meta['type'] == 'textarea' )
        get_meta_textarea( $meta, $value );
        elseif ( $meta['type'] == 'select' )
        get_meta_select( $meta, $value );

        endforeach; ?>

        <label for="">

        <input type="text" name="" id="" value="" size="30" tabindex="30" style="width: 97%;" />
        <input type="hidden" name="_noncename" id="_noncename" value="" />

        <label for="">

        <select name="" id="">

        <option >

        <input type="hidden" name="_noncename" id="_noncename" value="" />

        <label for="">

        <textarea name="" id="" cols="60" rows="4" tabindex="30" style="width: 97%;">
        <input type="hidden" name="_noncename" id="_noncename" value="" />


        .-= David M Sawyer´s last blog ..Free Just Courage audiobook by Gary A. Haugen =-.

        Reply to this comment
        • Alex Denning

          31. Oct, 2009

          I’ll have to have a look into this problem people are having – it’s not happening to me, that’s for sure! It certainly is a great way to offer custom fields.

          Reply to this comment
      • Brian

        31. Oct, 2009

        Hi Alex,

        Thanks for the offer of help but I was stuck on a deadline and went for a different approach, using a different tutorial. However, if you are curious then here is the code – http://pastie.org/677575

        One thing I would like to know about your method of making a new meta box is that can you still use ‘the_meta’ and also ‘custom_meta’ commands. According to comments in the wordpress forum, and as I have now found out, when you make your own custom fields panel the only way to access the info is by using get_post_meta!!

        How strange.

        I’m now trying to add tinyMCE onto a ‘textarea’…. any ideas?

        Thanks,

        Brian

        Reply to this comment
        • Alex Denning

          31. Oct, 2009

          If I’m thinking right then get_post_meta is the only way to pull a custom field, no?

          A better option would be to use WordPress’ own WYSIWYG editor.

          Reply to this comment
          • Brian

            31. Oct, 2009

            Hi Alex,

            Using the info from WordPress itself -

            http://codex.wordpress.org/Using_Custom_Fields

            - you can see the following uses for getting the info from your custom field –

            the_meta()
            get_post_meta()
            get_post_custom()
            get_post_custom_values()
            get_post_custom_keys()

            ….apparently when you make a custom write panel in the admin area you lose the use of all but ‘get_post_meta’.

            Don’t worry, this isn’t a finger-pointing exercise, I just wanted to know if you knew of this and possibly a work around so individual areas of data could be called in the future – as I actually need.

            Regarding the use WordPress’ own WYSIWYG editor this is what I am trying but, being a newbie, I don’t know how to call a Javascript file and place Javascript within my functions.php.

            Thanks for any help,

            Brian

          • Alex Denning

            05. Nov, 2009

            Fair point. Now you mention it, those other options do ring a bell :)

            Calling JS within functions is easy – depending how you’re doing it you can either close out the php and call the JS as normal or echo it. Google those for a better explanation :) .

  6. Yes_Pap

    14. Dec, 2009

    Hello,

    Do you know how to use the select option ?

    I want to create a select meta boxe with a true/false choice.

    Thx for your help.

    Reply to this comment
    • Yes_Papa@mac.com

      16. Dec, 2009

      Any ideas how to do this ?

      Could give me an example ?

      Thx for your help.

      Reply to this comment
  7. Karl Bedingfield

    01. Jan, 2010

    Fantastic tutorial!

    Just one question. I would like to put a brief description under each input field as a reminder to what each input does.

    How would I do that?

    Thanks,
    Karl

    Reply to this comment
    • Alex Denning

      03. Jan, 2010

      Literally just add in a paragraph with what you want to say: <p>This does so and so.</p>

      Reply to this comment
  8. Jason

    11. Jan, 2010

    Great post! Very helpful.

    Quick question though…

    Is there any way to make the meta box show only when a specific page template is selected?

    Reply to this comment
    • Alex Denning

      18. Jan, 2010

      You might be able to do so with Ian Stewart’s conditional sidebar stuff.

      Reply to this comment
    • Jason

      18. Jan, 2010

      Thanks for the reply! It’s funny you linked to that post. I’ve been following ThemeShaper tutorials in building my little WP framework over the last couple of months.

      As far as making a meta box show on a Page Write admin page only when a specific page template is selected, I ended up just using javascript.

      I figured any solution with PHP would not allow the user to see the new meta box until they actually saved the page and came back to editing it again (which wouldn’t make sense).

      Reply to this comment
    • Jason

      24. Jan, 2010

      In creating a WordPress CMS theme, I wanted the typical blog looking page to be a page template. However with that page template, I wanted the user to be able to select which categories they would like to be feed into that specific blog page. So I created a meta box basically how it was done in this tutorial that listed the blog categories and gave the users checkboxes to check off which categories they wanted to use.

      The only problem was that I was worried my users would be confused if they were creating a page that wasn’t a blog page (like a contact or info page or something) and they saw a box that said “Which categories would you like to include in this blog page?”

      So, I created a meta box with the id “blog-options-meta” and my goal was that when the user is in “Edit Page” page, and they selected my “Blog Page” template under the Attributes > template drop down menu, then my “blog-options-meta” meta box would slide down and appear on the screen.

      Here’s a screenshot so everyone knows what the heck I’m talking about:
      http://jasonbobich.com/jbobich_framework_blog_options.jpg

      When you create a meta box, the id of that metabox is inserted into the HTML div tag when WordPress prints out that meta box, which made it easy to target it with jQuery.

      $(document).ready(function(){

      //check if initially selected
      if ($(‘#page_template’).val() == “template_blog.php” ) {
      $(“#blog-options-meta”).show();
      }

      //Targets WP’s template drop down menu
      $(“#page_template”).click(function(){

      //If they select my blog template, slide the meta box down
      if ($(‘#page_template’).val() == “template_blog.php” ) {

      $(“#blog-options-meta”).slideDown(“normal”);

      // if they select any other option, remove the meta box
      } else {

      $(“#blog-options-meta”).slideUp(“normal”);

      }

      });
      });

      *Note that the id “page_template” is what WordPress gives the drop down menu, that I was targeting. So, realistically, I have no control over that id.

      Obviously, for this to work you need to insert your javascript into some JS file and add that to your WordPress admin head along with jQuery. You would also want to include some CSS that initially set your meta box div to “display:none”. You would use the admin_head function to add the js files and css file to your WP admin section. (Google “WordPress admin_head” if you’re unfamiliar with how to do that.) In my case it makes the most sense to do it this way because I’m selling a WordPress theme where I obviously only have control over the theme folder.

      Reply to this comment
  9. Paul

    01. Feb, 2010

    What
    return apply_filters( ‘hybrid_post_meta_boxes’, $meta_boxes );

    do ?

    I’m interested why you use apply_filter instead of add_filter ?

    Reply to this comment
  10. philip

    25. Apr, 2010

    thanks a lot for this help.

    i try to use it with qtranslate with ( [:en] ) and ( ) tags but with no luck.
    is a way to make it work with qtranslate tags also?

    thanks a lot again!

    philip

    Reply to this comment
  11. Josh Byers

    23. Jun, 2010

    Regarding only showing custom meta boxes when a certain page template is selected I have this solution which works great:


    $post_id = $_GET['post'] ? $_GET['post'] : $_POST['post_ID'] ;
    $template_file = get_post_meta($post_id,'_wp_page_template',TRUE);

    if ($template_file == 'attorneys.php') { // this will only show on pages that have been saved with the attorneys template

    Just replace “attorneys.php” with the name of your template file,
    Include the custom meta box code and close out the open brace.

    Reply to this comment
  12. chris

    09. Aug, 2010

    How to use select:


    'password' => array(
    'name' => 'password',
    'title' => __('Password Protection'),
    'options' => array(
    'No',
    'Yes'
    ),
    'type' => 'select' )

    Reply to this comment
    • philip

      25. Sep, 2010

      thanks Chris but how you call an if statement here?

      i need to make a show/hide dropdown,
      if is show
      //get php file
      else
      //do nothing

      thanks a lot!

      Reply to this comment
  13. Extension:103

    15. Aug, 2010

    im hoping you can help me out with this one. i have had this code in my theme from theme hybrid for over a year now. and noticed no problems. now i have been developing a theme for entry into the wordpress theme directory.

    after going through all the usually stuff i came to debug the theme. i keep getting an error saying this

    “Notice: Undefined index: post_type in……”

    and

    “Notice: Undefined index: Title_noncename in ……”

    now this issue is coming from the hybrid_save_meta_data function, heres the code for reference

    does anyone have a solution to this?

    i have a okay understanding of php but this is a real issue and i cant figure it out.

    Reply to this comment
  14. acepek

    27. Aug, 2010

    Thank you very much for this!

    I have changed it a bit to suit my needs by adding extra metaboxes. These all display fine but only the first set (the first 5) save! Of course there is something I need to change to make it save the extras but alas, I am just a tinkerer not a master…


    $meta_boxes = array(
    'url' => array( 'name' => 'URL', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title' => array( 'name' => 'Title', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description' => array( 'name' => 'Description', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll' => array( 'name' => 'Preroll', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' ),
    'link' => array( 'name' => 'link', 'title' => __('link:', 'hybrid'), 'type' => 'tag' ),

    'url1' => array( 'name' => 'URL1', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title1' => array( 'name' => 'Title1', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description1' => array( 'name' => 'Description1', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll1' => array( 'name' => 'Preroll1', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' ),
    'link1' => array( 'name' => 'link1', 'title' => __('link:', 'hybrid'), 'type' => 'tag' ),

    'url2' => array( 'name' => 'URL2', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title2' => array( 'name' => 'Title2', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description2' => array( 'name' => 'Description2', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll2' => array( 'name' => 'Preroll2', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' ),
    'link2' => array( 'name' => 'link2', 'title' => __('link:', 'hybrid'), 'type' => 'tag' ),

    'url3' => array( 'name' => 'URL3', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title3' => array( 'name' => 'Title3', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description3' => array( 'name' => 'Description3', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll3' => array( 'name' => 'Preroll3', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' ),
    'link3' => array( 'name' => 'link3', 'title' => __('link:', 'hybrid'), 'type' => 'tag' ),

    'url4' => array( 'name' => 'URL4', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title4' => array( 'name' => 'Title4', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description4' => array( 'name' => 'Description4', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll4' => array( 'name' => 'Preroll4', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' ),
    'link4' => array( 'name' => 'link4', 'title' => __('link:', 'hybrid'), 'type' => 'tag' ),

    'url5' => array( 'name' => 'URL5', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title5' => array( 'name' => 'Title5', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description5' => array( 'name' => 'Description5', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll5' => array( 'name' => 'Preroll5', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' ),
    'link5' => array( 'name' => 'link5', 'title' => __('link:', 'hybrid'), 'type' => 'tag' ),

    'url6' => array( 'name' => 'URL6', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title6' => array( 'name' => 'Title6', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description6' => array( 'name' => 'Description6', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll6' => array( 'name' => 'Preroll6', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' ),
    'link6' => array( 'name' => 'link6', 'title' => __('link:', 'hybrid'), 'type' => 'tag' ),

    'url7' => array( 'name' => 'URL7', 'title' => __('Video URL:', 'hybrid'), 'type' => 'text' ),
    'title7' => array( 'name' => 'Title7', 'title' => __('Title:', 'hybrid'), 'type' => 'text' ),
    'description7' => array( 'name' => 'Description7', 'title' => __('Description:', 'hybrid'), 'type' => 'text' ),
    'preroll7' => array( 'name' => 'Preroll7', 'title' => __('Preroll?', 'hybrid'),'options' => array('','Yes'), 'type' => 'select' )

    );

    So… how do I get the save function to cycle through each of these and save them also? I thought it would just happen as all I really did was add to the array, but obviously I was wrong. Also just to note, the “tag” type I added in and is not for saving, just layout. Whether I get help or not, thank you for the great post!

    Reply to this comment
  15. Rob Malon

    08. Oct, 2010

    I was doing something like this for a while. It was a pain to manage so I did some searching. Found the Verde Meta Box plugin and found a way to convert my existing custom fields to be used in it. Its not without bugs but I’ve outlined both of these things here: http://robmalon.com/creating-wordpress-custom-field-boxes-from-existing-meta-data/

    Reply to this comment
  16. Patricia

    03. Dec, 2010

    Hi, I really like the way this is done. Would it be recommended to insert a custom field with keywords as well or is this not needed anymore?

    Reply to this comment
  17. Jan Fabry

    13. Jan, 2011

    I expanded this code with support for a group of checkboxes, in response to a question on the WordPress Stack Exchange. Feel free to use it too, or maybe integrate it in the base file!

    Reply to this comment
  18. anuj

    17. Feb, 2011

    i must say that simply gr8 tip :)

    Reply to this comment
  19. Michael

    25. Feb, 2011

    Hi, I’ve stumbled across your code and it is the perfect solution for what I need to do but when I try putting it in to my functions.php file it gives me the following error

    Warning: Cannot modify header information – headers already sent by (output started at /usr/var/www/localhost/htdocs/oowebsite/wp-includes/plugin.php:395) in /usr/var/www/localhost/htdocs/oowebsite/wp-admin/theme-editor.php on line 89

    I’m inserting it directly at the top of the functions file to call it as early as possible, am I putting it in the wrong place? Any feeback very much obliged.

    Reply to this comment
  20. Marco Berrocal

    17. Oct, 2011

    Does anybody know how to loop this? Say I want to do a slider for pages with the meta box set to TRUE or something, and then I want to grab all pages or posts with that condition?

    Reply to this comment
  21. Petra

    08. Dec, 2011

    Thanks for the tutorial. I tried to implement your code and seems to be working fine, only that I am getting two sets of custom fields: I get my own custom write panel with custom fields and the one that comes with WordPress. For some reason when I add a custom field in my custom write panel, it also automatically adds it into a default custom field panel, so I have two custom fields with the same name and content. Any ideas why and how to resolve this problem? I am using the latest version of WordPress.

    Reply to this comment
  22. dustin

    05. Jan, 2012

    Thanks so much for this tutorial!

    Reply to this comment

Trackbacks/Pingbacks

  1. [...] Create An In-Post (Theme) Options (Meta) Box in WordPress [...]

  2. [...] and it inherits all of Biblioteca’s advanced features – a nice theme options page, in post SEO options, threaded comments, a ton of widget ready area etc.The theme would look great on a personal blog or [...]

  3. [...] in the sidebar of our blog.HypothesisUse of custom fields to pull data from posts. Preferably custom write panels to spice it up a bit.Loop (preferably without replacing the loop already in use) to pull a random [...]

  4. [...] the first post – WPShout – is actually a link to WPShout. How? Using Biblioteca’s custom write meta box thingys (I still don’t know the technical term!) I can create a new post which contains the link and [...]

  5. [...] Each offer is a post but we only want one line of text briefly describing the offer. We've built a custom meta box to allow an easy way of adding custom fields to posts. The custom field contains information about [...]

  6. [...] that were as straight-forward as I was hoping there would be. The best tutorial I found was located here. The problem with this tutorial was that it didn’t spell it out clearly enough for me. It was [...]

Leave a Reply

Please use your real name when commenting. Wrap code in <code> tags and make sure HTML is encoded. You can use regular HTML like <a href="... etc.

Get yours questions answered quicker

If you're using this post for paid work and have a question of any complexity then please ask at WPQuestions where you'll get a prompt response.