SIC Digital Blog

We make things for the internet and we love it.

How to Create a Custom Post Type with Image Uploads For WordPress 3

I’ve been working on a project to create a CMS for a series of dental websites. One of the important things is to be able to make the CMS as simple as possible for the end users, so I’ve set out using WordPress 3′s new custom post types to create and display these nice and neat. For this example I wanted to create a post type for “Before and After” images. Rather than having the end user have to go to media, upload it, and then grab the link for the page I wanted to have them to be able to go in to a “Before and After” post type and simply upload1 upload2 and press publish. Here’s how I went about doing it.

Step 1 : Create the Custom Post type

Custom post types are pretty easy to create:

// Creates before and after post type
add_action('init', 'post_type_before_after');
function post_type_before_after()
{
  $labels = array(
    'name' => _x('Before and Afters', 'post type general name'),
    'singular_name' => _x('Before and After', 'post type singular name'),
    'add_new' => _x('Add New', 'before_and_after'),
    'add_new_item' => __('Add New Before and After')
 
  );
 
 $args = array(
    'labels' => $labels,
    'public' => true,
    'publicly_queryable' => true,
    'show_ui' => true,
    'query_var' => true,
    'rewrite' => true,
    'capability_type' => 'post',
    'hierarchical' => true,
    'menu_position' => null,
    'supports' => array('title','excerpt'));
 
  register_post_type('before_and_after',$args);
 
}

Step 2: Creating the meta boxes

The custom post type above if you look at the code

 'supports' => array('title','excerpt')); 

What this does is tell WordPress what stuff you want on the admin page. I only want the title and excerpt fields on mine because I’m going to add some extras. You could also add, “editor”,
comments” etc..

<?php
$prefix = 'sic_';
 
$meta_box = array(
	'id' => 'my-meta-box',
	'title' => 'Before and Afters',
	'page' => 'before_and_after',
	'context' => 'normal',
	'priority' => 'high',
	'fields' => array(
		array(
			'name' => 'Before',
			'desc' => 'Select a Before Image',
			'id' => 'upload_image',
			'type' => 'text',
			'std' => ''
		),
				array(
			'name' => '',
			'desc' => 'Select an After Image',
			'id' => 'upload_image_button',
			'type' => 'button',
			'std' => 'Browse'
		),
	array(
			'name' => 'After',
			'desc' => 'Select an After Image',
			'id' => 'upload_image2',
			'type' => 'text',
			'std' => ''
		),
	array(
			'name' => '',
			'desc' => '',
			'id' => 'upload_image_button2',
			'type' => 'button',
			'std' => 'Browse'
		),
	)
);
 
add_action('admin_menu', 'mytheme_add_box');
 
// Add meta box
function mytheme_add_box() {
	global $meta_box;
 
	add_meta_box($meta_box['id'], $meta_box['title'], 'mytheme_show_box', $meta_box['page'], $meta_box['context'], $meta_box['priority']);
}
 
// Callback function to show fields in meta box
function mytheme_show_box() {
	global $meta_box, $post;
 
	// Use nonce for verification
	echo '<input type="hidden" name="mytheme_meta_box_nonce" value="', wp_create_nonce(basename(__FILE__)), '" />';
 
	echo '<table class="form-table">';
 
	foreach ($meta_box['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']) {
 
 
 
 
//If Text		
			case 'text':
				echo '<input type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta ? $meta : $field['std'], '" size="30" style="width:97%" />',
					'<br />', $field['desc'];
				break;
 
 
//If Text Area			
			case 'textarea':
				echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="4" style="width:97%">', $meta ? $meta : $field['std'], '</textarea>',
					'<br />', $field['desc'];
				break;
 
 
//If Button	
 
				case 'button':
				echo '<input type="button" name="', $field['id'], '" id="', $field['id'], '"value="', $meta ? $meta : $field['std'], '" />';
				break;
		}
		echo 	'<td>',
			'</tr>';
	}
 
	echo '</table>';
}
 
add_action('save_post', 'mytheme_save_data');
 
// Save data from meta box
function mytheme_save_data($post_id) {
	global $meta_box;
 
	// verify nonce
	if (!wp_verify_nonce($_POST['mytheme_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['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);
		}
	}
}
 
function my_admin_scripts() {
wp_enqueue_script('media-upload');
wp_enqueue_script('thickbox');
wp_register_script('my-upload', get_bloginfo('template_url') . '/functions/my-script.js', array('jquery','media-upload','thickbox'));
wp_enqueue_script('my-upload');
}
function my_admin_styles() {
wp_enqueue_style('thickbox');
}
add_action('admin_print_scripts', 'my_admin_scripts');
add_action('admin_print_styles', 'my_admin_styles');

Ok so what this has done is write all of the meta box fields that you want. The php reads what you put in the array and all of those switch cases check to see what kind of input field it is then create the format accordingly. You can copy and paste that exactly as is and it will work for this tutorial.

This should leave you with

Step 3: Getting the WordPress Media Upload working for the browse buttons

So now we have the meta boxes for the custom field but what we want is the end user to be able to click browse and upload an image or select from the gallery. Just for usability sake you know? Heres how we do it.

If you look at the code above

 function my_admin_scripts() {
wp_enqueue_script('media-upload');
wp_enqueue_script('thickbox');
wp_register_script('my-upload', get_bloginfo('template_url') . '/functions/my-script.js', array('jquery','media-upload','thickbox'));
wp_enqueue_script('my-upload');
}
function my_admin_styles() {
wp_enqueue_style('thickbox');
}
add_action('admin_print_scripts', 'my_admin_scripts');
add_action('admin_print_styles', 'my_admin_styles');

This loads the wp_enqueue_script(‘thickbox;), as well as registers the “my-upload” function which will be used to link to some jquery that adds functionality to our browse buttons.

Step 4: The Jquery for the Browse Buttons

jQuery(document).ready(function() {
 
jQuery('#upload_image_button').click(function() {
											  window.send_to_editor = function(html) {
 imgurl = jQuery('img',html).attr('src');
 jQuery('#upload_image').val(imgurl);
 tb_remove();
 
 
}
 
 
 tb_show('', 'media-upload.php?post_id=1&amp;type=image&amp;TB_iframe=true');
 return false;
});
 
 
});
 
jQuery(document).ready(function() {
 
jQuery('#upload_image_button2').click(function() {
											   window.send_to_editor = function(html) {
 imgurl = jQuery('img',html).attr('src');
 jQuery('#upload_image2').val(imgurl);
 tb_remove();
 
 
}
 
 tb_show('', 'media-upload.php?post_id=1&amp;type=image&amp;TB_iframe=true');
 return false;
});
 
 
 
});

Want to learn more WordPress?

This book is way worth checking out if your just getting in to WordPress. Chris Coyier is awesome and this book is a great place to start.

About the Author

MichaelMichael is a WordPress developer and speaker based out of Miami Beach, FL.View all posts by Michael →

  1. sereneserene01-16-2012

    thanks for this great tut!

    one question: i have made a single select box type and works great.

    but what about multiple select, and checkbox? it does not return all selected values, only the last one selected.
    any tips on these without involving javascript? i have jquery method but i would not use that if it can be avoided.

    thanks!

  2. sereneserene01-17-2012

    figured it out :)

Leave a Reply

Have a question? Give us a call! 305-741-4742