Sponsored by

  • Intel
  • HP

WordPressHow to

User-friendly custom fields with Meta Boxes in WordPress

User-friendly custom fields with Meta Boxes in WordPress

Ryan Taylor explains how to add metadata to a WordPress post by creating and adding Meta Boxes and improving the usability of custom fields.

  • Knowledge needed: PHP, experience with WordPress
  • Requires: WordPress
  • Project Time: 30 minutes

In a previous tutorial I talked about Post Formats, a new feature introduced in WordPress 3.1. A Post Format is a piece of meta information that can be assigned to individual posts and used by a theme to customise the presentation of those posts. I also discussed the current limitations of Post Formats in WordPress when compared to services like Tumblr. With Tumblr, whichever Post Format you select determines the form fields youre presented with. In Wordpress, by default, you only have the title and post editor fields.

We can of course add additional metadata to a post by using Custom Fields:

The problem with Custom Fields is they’re not very user-friendly. If you’re designing for a client you need to explain what they are, what needs to be entered and also hope they don’t forget to do it.

This is where Meta Boxes come in handy!

01. What are Meta Boxes?

A Meta Box is a custom section that can be added to a post/page screen. It can be used to group Custom Fields together and give them context. Here’s a Meta Box that I use in conjunction with Post Formats for my blog (ryanhavoctaylor.com):

You can have as many form fields as you need in a Meta Box as well as use other input types such as checkboxes and radio buttons. Under the hud, they’re still Custom Fields and you call the values in your theme the exact same way:

get_post_meta($post_id, $key, $single);

We’re just making the admin UI more usable with labels, instructions and better formatting.

Advertisement

02. Create a Meta Box

When I build WordPress themes I use Meta Boxes with my posts all the time and often I have Custom Post Types (codex.wordpress.org/Post_Types) registered that I also want to have Meta Boxes applied to.

The code I’m now going to talk you through will enable you to quickly add Meta Boxes to any and all of your themes Post Types.

We start off by adding the following code to our functions.php template file (if this file doesn’t exist in your theme then create it):

//We create an array called $meta_box and set the array key to the relevant post type
$meta_box['post'] = array(
    
    //This is the id applied to the meta box
    'id' => 'post-format-meta',   
    
    //This is the title that appears on the meta box container
    'title' => 'Additional Post Format Meta',    
    
    //This defines the part of the page where the edit screen section should be shown
    'context' => 'normal',    
    
    //This sets the priority within the context where the boxes should show
    'priority' => 'high',
    
    //Here we define all the fields we want in the meta box
    'fields' => array(
        array(
            'name' => 'Link - URL',
            'desc' => 'URL for the link',
            'id' => 'pf_link_url',
            'type' => 'text',
            'default' => ''
        ),
        array(
            'name' => 'Quote - Source',
            'desc' => '(Optional) URL to the quote source',
            'id' => 'pf_quote_source',
            'type' => 'text',
            'default' => ''
        )
    )
);

This is simply an array declaration that we will pass to a series of functions to create our Meta Box. We’re going to look at those functions next, but once they’re written, all you’ll need to do is add array entries like the one above to your function.php file to quickly add Meta Boxes to your themes.

The above entry will add the Additional Post Format Meta box that I use on my blog to the post screen.

If you’re using Custom Post Types you can add a Meta Box to them as well by adding another array entry. Here’s an example for a Post Type called Books:

 $meta_box['books'] = array(
    'id' => 'book-meta-details',
    'title' => 'Book Meta Details',
    'context' => 'normal',
    'priority' => 'high',
    'fields' => array(
        array(
            'name' => 'Summary',
            'desc' => '(Max 45 words) Note: Leave all other fields blank if the book is not on sale yet.',
            'id' => 'book_summary',
            'type' => 'textarea',
            'default' => ''
        ),
        array(
            'name' => 'Buy Now URL:',
            'desc' => '',
            'id' => 'book_ buy_now_link',
            'type' => 'text',
            'default' => ''
        ),
        array(
            'name' => 'Price:',
            'desc' => 'e.g. £9.95',
            'id' => 'book_price',
            'type' => 'text',
            'default' => ''
        ),
        array(
        'name' => 'Book is on sale?',
            'desc' => '',
            'id' => 'book_on_sale',
            'type' => 'checkbox',
            'default' => ''
      ),
        array(
            'name' => 'Sample PDF Url',
            'desc' => '(Optional) Link to a sample PDF.',
            'id' => 'book_sample_url',
            'type' => 'text',
            'default' => ''
        )
    )
);
 

Notice that we change the array key to reflect the post type that the entry applies to. Once you’ve created all the array entries that you want you need to add the following line of code to run the functions that will actually create the Meta Box(es).

add_action('admin_menu', 'plib_add_box'); 

Note that this line only needs to be run once.

03. Keeping everything tidy

This is an optional step, but to keep everything tidy I’ve created a file called preset-library.php, which I add to my themes and include at the top of function.php like so:

include('preset-library.php');

I find separating functions that never change from the code that calls them easier to work with than having everything clumped together.

If you want to do this too, add the following functions to preset-library.php, otherwise add them to the top of functions.php.

04. Adding the Meta Box

The first function is a relatively simple one.

//Add meta boxes to post types
function plib_add_box() {
    global $meta_box;
    
    foreach($meta_box as $post_type => $value) {
        add_meta_box($value['id'], $value['title'], 'plib_format_box', $post_type, $value['context'], $value['priority']);
    }
}

We loop through the $meta_box array we defined earlier and pass each entry into the WordPress function add_meta_box (codex.wordpress.org/Function_Reference/add_meta_box). You’ll see that one of the parameters for this function is a callback to another function called plib_format_box. We’ll cover this one next.

05. Formatting the Meta Box

This function applies the HTML formatting within the Meta Box for each input field.

//Format meta boxes
function plib_format_box() {
  global $meta_box, $post;

  // Use nonce for verification
  echo '<input type="hidden" name="plib_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';

  echo '<table class="form-table">';

  foreach ($meta_box[$post->post_type]['fields'] as $field) {
      // get current post meta data
      $meta = get_post_meta($post->ID, $field['id'], true);

      echo '<tr>'.
              '<th style="width:20%"><label for="'. $field['id'] .'">'. $field['name']. '</label></th>'.
              '<td>';
      switch ($field['type']) {
          case 'text':
              echo '<input type="text" name="'. $field['id']. '" id="'. $field['id'] .'" value="'. ($meta ? $meta : $field['default']) . '" size="30" style="width:97%" />'. '<br />'. $field['desc'];
              break;
          case 'textarea':
              echo '<textarea name="'. $field['id']. '" id="'. $field['id']. '" cols="60" rows="4" style="width:97%">'. ($meta ? $meta : $field['default']) . '</textarea>'. '<br />'. $field['desc'];
              break;
          case 'select':
              echo '<select name="'. $field['id'] . '" id="'. $field['id'] . '">';
              foreach ($field['options'] as $option) {
                  echo '<option '. ( $meta == $option ? ' selected="selected"' : '' ) . '>'. $option . '</option>';
              }
              echo '</select>';
              break;
          case 'radio':
              foreach ($field['options'] as $option) {
                  echo '<input type="radio" name="' . $field['id'] . '" value="' . $option['value'] . '"' . ( $meta == $option['value'] ? ' checked="checked"' : '' ) . ' />' . $option['name'];
              }
              break;
          case 'checkbox':
              echo '<input type="checkbox" name="' . $field['id'] . '" id="' . $field['id'] . '"' . ( $meta ? ' checked="checked"' : '' ) . ' />';
              break;
      }
      echo     '<td>'.'</tr>';
  }

  echo '</table>';

}

The function loops through the fields section of each entry of the $meta_box array and prints out the supplied values.

06. Saving data from the Meta Box

Finally we need to tell WordPress that the fields exist and how to save them with the Post.

// Save data from meta box
function plib_save_data($post_id) {
    global $meta_box,  $post;
    
    //Verify nonce
    if (!wp_verify_nonce($_POST['plib_meta_box_nonce'], basename(__FILE__))) {
        return $post_id;
    }

    //Check autosave
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return $post_id;
    }

    //Check permissions
    if ('page' == $_POST['post_type']) {
        if (!current_user_can('edit_page', $post_id)) {
            return $post_id;
        }
    } elseif (!current_user_can('edit_post', $post_id)) {
        return $post_id;
    }
    
    foreach ($meta_box[$post->post_type]['fields'] as $field) {
        $old = get_post_meta($post_id, $field['id'], true);
        $new = $_POST[$field['id']];
        
        if ($new && $new != $old) {
            update_post_meta($post_id, $field['id'], $new);
        } elseif ('' == $new && $old) {
            delete_post_meta($post_id, $field['id'], $old);
        }
    }
}

add_action('save_post', 'plib_save_data');

07. Conclusion

And that’s it! If your themes need more information than the basic title and post editor fields then Meta Boxes are a great way to improve the usability of Custom Fields for the user, whether they’re technical or not.

Ryan Taylor ryanhavoctaylor.com/ is a freelance designer and front-end developer. He runs his own business at Havoc Inspired (havocinspired), blogs at ryanhavoctaylor.com and tweets under @ryanhavoc (twitter.com/ryanhavoc). He’s obsessed with clean, efficient and semantic HTML, CSS and jQuery (his favourite framework).

Advert

Log in to Creative Bloq with your preferred social network to comment

OR

Log in with your Creative Bloq account

site stat collection