treehouse : what would you like to learn today?
Web Design Web Development iOS Development

WordPress 3.0 - Custom Post Types and Meta Boxes

  • Hello,

    I am posting this here to help a buddy from Twitter figure out a solution to a problem he ran into.

    So, the problem was needing to create user-editable additional content for a post like seen in the picture. http://twitpic.com/27fpu0

    The way I accomplished this was to create a custome post type ( I reused one from a test theme I was working on called "achievement"

    in the functions file...
    add_action('init', 'wlg_cstm_register');  

    function wlg_cstm_register() {

    $achievement_labels = array(
    'name' => _x('Achievements', 'post type general name'),
    'singular_name' => _x('Achievement', 'post type singular name'),
    'add_new' => _x('Add New', 'achievement'),
    'add_new_item' => __('Add New Achievements'),
    'edit_item' => __('Edit Achievements'),
    'new_item' => __('New Achievement'),
    'view_item' => __('View Achievements'),
    'search_items' => __('Search Achievements'),
    'not_found' => __('No achievements found'),
    'not_found_in_trash' => __('No achievements found in Trash'),
    'parent_item_colon' => ''
    );

    $achievement_args = array(
    'labels' => $achievement_labels,
    'public' => true,
    'show_ui' => true,
    'capability_type' => 'post',
    'hierarchical' => false,
    'rewrite' => true,
    'supports' => array('title', 'editor', 'thumbnail')
    );


    register_post_type( 'achievement' , $achievement_args );
    }


    This code create a new post type called "achievement"

    I also added a custom meta box (this is basically like hard coding a custom field.)


    add_action("admin_init", "admin_init");
    add_action('save_post', 'save_points');

    function admin_init(){
    add_meta_box("achievementInfo-meta", "Achievement Points", "achievement_meta_options", "achievement", "side", "low");

    }

    function achievement_meta_options(){
    global $post;
    $custom = get_post_custom($post->ID);
    $points = $custom["points"][0];
    ?>
    <label>Points:</label><textarea rows="10" cols="60" name="points"><?php echo $points; ?></textarea>
    <?php
    }


    function save_points(){
    global $post;
    update_post_meta($post->ID, "points", $_POST["points"]);
    }

    It creates a textarea called "points" and adds this meta box only to the "achievement" post type. It then saves the value to a points meta option upon update.

    I then created a new file in my theme called single-achievement.php (this determines how the single achievement post will look.)


    <?php the_post(); ?>

    <?php
    $custom = get_post_custom($post->ID);
    $display_points = $custom["points"][0];
    ?>

    <div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    <h1 class="entry-title"><?php the_title(); ?></h1>



    <div class="entry-meta">

    <div class="entry-content">
    <?php
    if ( has_post_thumbnail() ) {
    the_post_thumbnail();
    }
    ?>
    <?php the_content(); ?>

    <div class="editable">
    <?php echo $display_points; ?>
    </div>
    </div>
    </div>


    Basically it just gets the content, the "points" value, and title.

    To show the posts in the main loop, I just did a query_posts and got both the "post" post type, and the custom "achievement" post type....

    <?php query_posts( array( 'post_type' => array('post', 'achievement') ) );
    ?>
    <?php if (have_posts()) : while (have_posts()) : the_post(); ?>

    <div <?php post_class() ?> id="post-<?php the_ID(); ?>">

    <h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>

    <?php include (TEMPLATEPATH . '/inc/meta.php' ); ?>

    <div class="entry">

    <?php the_content(); ?>
    </div>

    <div class="postmetadata">
    <?php the_tags('Tags: ', ', ', '<br />'); ?>
    Posted in <?php the_category(', ') ?> |
    <?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?>
    </div>

    </div>

    <?php endwhile; ?>

    You can see it in action here, there is no styling on the theme...
    http://tests.dingledoodle.com/diet/

    I made the custom meta HTML lists to make sure HTML input works there.

    To add a second, just make a second meta box like above, and display that second meta info in the single-achievement.php template.
  • Thanks a ton man for writing this up, big help.
    I am not clear on the last piece of code though, to 'show the posts in the main loop' the one with the query,
    where does that get used? Does the code above it, in the single-achievement.php file not display the posts from that category?

    Thanks again!
  • Hey thanks for sharing this :) great place to post it, I am sure lot's of people will find this useful :)
  • *Move to Tips & Tricks

    This is awesome! I've been looking for a proper tutorial like this for a while, but one step further.

    What I want to do is have not a text field meta box thing, but a place for a user to select an image.
  • Ryan,

    The "show the posts in the main loop" part is just saying that if you want the custom post type to show up in your main posts loop (say in the index.php, or home.php loop, you'll have to create a custom query as is in last section of code.

    Thanks for moving it, and the compliments!

    TheDoc,

    I'll look into trying that out in a bit, I think that could be cool...

    Though I believe if you weren't using the post thumbnail you could just utilize the "featured image" and post_thumbnail to accomplish what you might want...

    http://codex.wordpress.org/Post_Thumbnails
  • This is awesome! It's definitely one of my favorite tutorials for metaboxes!

    I have one question. what if I were going to create multiple metaboxes in a page and a post? is that much more difficult?
  • Mil gracias, Chris! It took me having to go through about four tutorials to remember, "let me see if Chris has something on this." Sure enough, you did, and it's much easier to understand and replicate compared to what I've been staring at for the past 2 hours.

    You're the man, as always.

  • @colorful_tones This was one of the posts that I saw that was more bulky and cumbersome than I needed.

  • Hey thanks for sharing this great place to post it, I am sure lot's of people will find this useful