Note: This is for older versions of WP < 3.9 prior to the new media upload being introduced
Here’s how to add fields and save the values on the category edit screen as well as a method of adding an image upload field.
Adding fields to category edit screen
To start we need to get some code showing up on the category edit screen.
add_action( 'edit_category_form_fields', 'my_category_custom_fields' );
add_action( 'edit_category', 'save_my_category_custom_fields' );
function my_category_custom_fields( $tag ) {
// your custom field HTML will go here
// the $tag variable is a taxonomy term object with properties like $tag->name, $tag->term_id etc...
// we need to know the values of our existing entries if any
$category_meta = get_option( 'category_meta' );
?>
<tr class="form-field">
<th scope="row" valign="top"><label for="category-title"><?php _e("Title"); ?></label></th>
<td>
<input id="category-title" name="category_meta[<?php echo $tag->term_id ?>]Category listing with thumbnail and description on home page" value="<?php if ( isset( $category_meta[ $tag->term_id ] ) ) esc_attr_e( $category_meta[ $tag->term_id ]['title'] ); ?>" />
<span class="description"><?php _e('Enter an alternative title for this category.'); ?></span>
</td>
</tr>
<!-- rinse & repeat for other fields you need -->
<?php
}
The simplest way to store our custom values is in the options table (there should be a taxonomy-meta table really but never mind). This way we only need to make one query to get the meta data for all of our categories. If anyone has a better idea for storage then speak up!
function save_my_category_custom_fields() {
if ( isset( $_POST['category_meta'] ) && !update_option('category_meta', $_POST['category_meta']) )
add_option('category_meta', $_POST['category_meta']);
}
For a checkbox you’re simply storing true or false so you’d use category_extras[$tag->term_id][show_on_home]
for the name attribute and use the value stored in $category_meta
to determine if it’s checked or not.
You may want to add some extra processing or sanitisation to the save function – mine is just a quick n dirty example.
The image field
This is a fair bit of code and quite complicated so I won’t explain it all here but the comments describe the purpose of each function. We can discuss in the comments if you want to.
The following functions add a link to the category edit screen which brings up the wordpress media library/image upload popup. You can then upload a picture and click to use it. You’ll then have the image ID and thumbnail url available to you with the other meta above.
// add the image size you need
add_image_size( 'category_thumb', 125, 125, true );
// setup our image field and handling methods
function setup_category_image_handling() {
// add the image field to the rest
add_action( 'edit_category_form_fields', 'category_image' );
global $pagenow;
if ( is_admin() ) {
add_action( 'admin_init', 'fix_async_upload_image' );
if ( 'edit-tags.php' == $pagenow ) {
add_thickbox();
add_action('admin_print_footer_scripts', 'category_image_send_script', 1000);
} elseif ( 'media-upload.php' == $pagenow || 'async-upload.php' == $pagenow ) {
add_filter( 'media_send_to_editor', 'category_image_send_to_editor', 1, 8 );
add_filter( 'gettext', 'category_image_replace_text_in_thickbox', 1, 3 );
}
}
}
add_action( 'admin_init', 'setup_category_image_handling' );
// the taxonomy edit screen image field
function category_image( $tag ) {
// get our category meta data
$category_meta = get_option('category_meta');
?>
<tr class="form-field hide-if-no-js">
<th scope="row" valign="top"><label for="taxonomy-image"><?php _e("Image"); ?></label></th>
<td>
<div id="taxonomy-image-holder">
<?php if( !empty($category_meta[$tag->term_id]['image']) ) { ?>
<img style="max-width:100%;display:block;" src="https://wordpress.stackexchange.com/questions/5955/<?php echo esc_attr( $category_meta[ $tag->term_id ]["image']['thumb'] ); ?>" alt="" />
<a id="taxonomy-image-select" class="thickbox" href="media-upload.php?is_term=true&type=image&TB_iframe=1"><?php _e('Change image'); ?></a>
<a class="deletion" id="taxonomy-image-remove" href="#remove-image">Remove image</a>
<?php } else { ?>
<a id="taxonomy-image-select" class="thickbox" href="media-upload.php?is_term=true&type=image&TB_iframe=1"><?php _e('Choose an image'); ?></a>
<?php } ?>
</div>
<input type="hidden" name="category_meta[<?php echo $tag->term_id ?>][image][id]" value="<?php if( isset($category_meta[ $tag->term_id ]['image']['id']) ) echo esc_attr($category_meta[ $tag->term_id ]['image']['id']); ?>" class="tax-image-id" />
<input type="hidden" name="category_meta[<?php echo $tag->term_id ?>][image][thumb]" value="<?php if( isset($category_meta[ $tag->term_id ]['image']['thumb']) ) echo esc_attr($category_meta[ $tag->term_id ]['image']['thumb']); ?>" class="tax-image-thumb" />
<span class="description"><?php _e('A category image.'); ?></span></td>
</tr>
<?php
}
// required for uploading images on non post/page screens
function fix_async_upload_image() {
if(isset($_REQUEST['attachment_id'])) {
$GLOBALS['post'] = get_post($_REQUEST['attachment_id']);
}
}
// are we dealing with the taxonomy edit screen?
function is_category_context() {
if ( isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'],'is_term') !== false ) {
return true;
} elseif ( isset($_REQUEST['_wp_http_referer']) && strpos($_REQUEST['_wp_http_referer'],'is_term') !== false ) {
return true;
} elseif ( isset($_REQUEST['is_term']) && $_REQUEST['is_term'] !== false ) {
return true;
}
return false;
}
// replace Insert Into Post text with something more appropriate
function category_image_replace_text_in_thickbox($translated_text, $source_text, $domain) {
if ( is_category_context() ) {
if ('Insert into Post' == $source_text) {
return __('Use this image', MB_DOM );
}
}
return $translated_text;
}
// output a script that sets variables on the window object so that they can be accessed elsewhere
function category_image_send_to_editor( $html, $id, $attachment ) {
// context check might not be necessary, and, might not work in all cases
if ( is_category_context() ) {
$item = get_post($id);
$src = wp_get_attachment_image_src($id,'thumbnail',true); // 0 = url, 1 = width, 2 = height, 3 = icon(bool)
?>
<script type="text/javascript">
// send image variables back to opener
var win = window.dialogArguments || opener || parent || top;
win.TI.id = <?php echo $id ?>;
win.TI.thumb = '<?php echo $src[0]; ?>';
</script>
<?php
}
return $html;
}
// write out the javascript that handles what happens when a user clicks to use an image
function category_image_send_script() { ?>
<script>
self.TI = {};
var tb_position;
function send_to_editor(h) {
// ignore content returned from media uploader and use variables passed to window instead
jQuery('.tax-image-id').val( self.TI.id );
jQuery('.tax-image-thumb').val( self.TI.thumb );
// display image
jQuery('#taxonomy-image-holder img, #taxonomy-image-remove').remove();
jQuery('#taxonomy-image-holder')
.prepend('<img style="max-width:100%;display:block;" src="'+ self.TI.thumb +'" alt="" />')
.append('<a class="deletion" id="taxonomy-image-remove" href="#remove-image">Remove image</a>');
jQuery('#taxonomy-image-select').html('Change image');
// close thickbox
tb_remove();
}
(function($){
$(document).ready(function() {
tb_position = function() {
var tbWindow = $('#TB_window'), width = $(window).width(), H = $(window).height(), W = ( 720 < width ) ? 720 : width;
if ( tbWindow.size() ) {
tbWindow.width( W - 50 ).height( H - 45 );
$('#TB_iframeContent').width( W - 50 ).height( H - 75 );
tbWindow.css({'margin-left': '-' + parseInt((( W - 50 ) / 2),10) + 'px'});
if ( typeof document.body.style.maxWidth != 'undefined' )
tbWindow.css({'top':'20px','margin-top':'0'});
};
return $('a.thickbox').each( function() {
var href = $(this).attr('href');
if ( ! href ) return;
href = href.replace(/&width=[0-9]+/g, '');
href = href.replace(/&height=[0-9]+/g, '');
$(this).attr( 'href', href + '&width=" + ( W - 80 ) + "&height=" + ( H - 85 ) );
});
};
$(window).resize(function(){ tb_position(); });
$("#taxonomy-image-select').click(function(event){
tb_show("Choose an image:", $(this).attr("href"), false);
return false;
});
$('#taxonomy-image-remove').live('click',function(event){
$('#taxonomy-image-select').html('Choose an image');
$('#taxonomy-image-holder img').remove();
$('input[class^="tax-image"]').val("");
$(this).remove();
return false;
});
});
})(jQuery);
</script>
<?php
}
Accessing the information
In your my_function
bit taken from your own answer you would then access the metadata like so:
function my_function(){
$args=array(
'orderby' => 'name',
'order' => 'ASC'
);
$categories=get_categories($args);
// get our category meta data and exit out if there isn't any
$category_meta = get_option('category_meta');
if ( !$category_meta )
return;
echo '<ul style="list-style-type:none;margin:0;padding:0">';
foreach($categories as $category) {
// skip unticked categories & categories with no meta data
if ( !isset( $category_meta[ $category->term_id ] ) || ( isset( $category_meta[ $category->term_id ] ) && !$category_meta[ $category->term_id ]['show_on_home'] ) )
continue;
echo '<li><a style="display:block;margin-top:20px;" href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '" ' . '>' . $category_meta[ $category->term_id ]['title'].'</a>';
if ( "" != $category_meta[ $category->term_id ]['image']['id'] )
echo wp_get_attachment_image( $category_meta[ $category->term_id ]['image']['id'], 'category_thumbnail', false, array( 'alt' => $category->name, 'class' => '' ) );
echo $category->description . '</li>';
}
echo '</ul>';
}