Introduction to custom posts


|

sculptor.jpg WordPress 3 give new instrument which make WP more powerful and wide abilities for make blogs and sites better. Custom posts allow to separate some objectives from posts and pages to make good treatment for files, events, news etc.

What really custom posts is ? Custom posts is new record in the posts table ( additionally to posts, pages and attachments ), add new item to the admin menu ( to top or below some menu point ), add new taxonomies like category for hierarchy or like tags for flat, add new rewrite point for permalink to see custom posts in UI. Some core features like widgets or system function still works only with system types of posts, but can be easily hooked or changed.

I will show how to use custom posts for files, testimonials, calendar events, form for add for users and many other features

Register the custom posts

First you have to register custom posts by register_post_type()

add_action('init', 'testimonials_init');
function testimonials_init() {
    $args = array(
        'labels' => array(
            'name' => __('Testimonials'),
            'singular_name' => __('Testimonials'),
            'add_new_item' => __('Add new testimonal'),
            'edit_item' => __('Edit testimonal'),
        ),
        'public' => true,
        'supports' => array('title', 'editor', 'thumbnail'),
        'rewrite' => true,
        'has_archive' => true,
        'permalink_epmask' => EP_PERMALINK
    );

    register_post_type( 'testimonials', $args );

    register_taxonomy(
        'testimonials',
        'testimonials',
        array (
            'hierarchical' => false,
            'labels' => array(
                'name' => __('Testimonials category'),
                'singular_name' => __('Testimonials category'),
            )
            )
    );
   
    if (!get_option('testimonials')) {
        flush_rewrite_rules();
        update_option('testimonials', true);
    }
}

You can place this registration in theme functions.php or in plugin activation hook and/or in settings update. Just keep related things together.

admin menu.png By this code we will receive admin submenu for testimonials with default list and ability to change content and title ( managed by supports field in registration ), use separated tags named ‘Testimonials category’ and request template for single custom post or list by url prefix http://example.org/testimonials/ ( list enabled by has_archive, prefix is type name by default, but you can change it by ‘rewrite’ => array( ‘slug’ => ‘some’ ) in registration )

New testimonials will not displayed in the normal posts query, but templates can be reused or separated by slug suffix ( eg list will use archive-testimonials.php )

You can query custom posts in template or widget by get_posts()

$loop = get_posts( array( 'post_type' => 'testimonials', 'posts_per_page' => 1 , 'orderby' => 'rand'));
foreach( $loop as $post ) {
    setup_postdata($post);
    get_template_part( 'content', 'testimonial' );
}

There get 1 random testimonial to show on home page.

Above we use only standard title and content of the post, but usually we need more properties to describe object

Meta values for posts

WordPress has meta values for post. You can set any values by update_post_meta() and read by get_post_meta(), but before you have to add input values in the user or admin form.

User form if under template control and you have to add code into template. Admin form for post of course has hook to insert, but more useful add_meta_box() function where you can ‘meta box’ into standard post form:

add_action('admin_menu', 'shopping_add_custom_box');
function shopping_add_custom_box() {
    add_meta_box('shopping_fields', __('Additionals for post'), 'shopping_fields', 'testimonials', 'normal', 'high');
}
function shopping_fields() {
    global $pe2_instance, $post;
    ?>
    <input type="hidden" name="shopping_noncename" id="shopping_noncename" value="<?php echo wp_create_nonce( __FILE__ ); ?/>" />
    <div class="alignleft">
    <label>URL<br />
    <input type="text" id="shopping_image_url" name="shopping_image_url" value="<?php $image = get_post_meta($post-/>ID, 'shopping_image_url',true); echo $image; ?>" size="45" /><br />
    </label>
    </div>
    < ?php
}

And in the save hook you can get $_POST[name] and write into meta:

add_action('save_post', 'shopping_fields_save_postdata');
function shopping_fields_save_postdata( $post_id ) {
    if ( !wp_verify_nonce( $_POST['shopping_noncename'], __FILE__ )) {
        return $post_id;
    }
    if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE )
        return $post_id;
    if ( !current_user_can( 'edit_post', $post_id ) )
        return $post_id;

    if (isset($_POST['shopping_image_url'])) {
        update_post_meta($post_id, 'shopping_image_url', esc_attr($_POST['shopping_image_url']));
    }
}

Take care about nonce field, avoid autosave and check the field name in the $_POST, because save from posts quick edit form and other can miss the field.

Template for the custom post can use meta values and show them or use for behavior modification. Additionally you can use meta values for sort or filter custom posts in the get_posts():

$loop = get_posts( array( 'post_type' => 'testimonials', 'nopaging' => true, 'meta_key' => 'shopping_image_url', 'orderby' => 'meta_value', 'order' => 'ASC' ));

WordPress has big ability to tuning the custom posts - add sortable fields in the posts list, show fields in the admin edit form, use compound meta query in custom posts selection and more and more ... I'll show some useful cases in the next posts.

feedback content * preview