This post has been marked as old. The code might no longer work. Comments have been disabled as this is no longer maintained.
In WordPress 3.5, the media gallery was completely rebuilt, and now the method described below doesn't work. Here's a tutorial that might help.
Images in WordPress can have as much metadata (data about the image) as you want. WordPress stores images as posts in the “attachment” post type, so all the standard WordPress functions you’re used to using with posts also work with images. For example, captions are stored as excerpts.
If you want to collect additional information on a post you typically use a metabox. For images, you can add your custom fields directly to the media uploader.
There’s two filters we’ll use: attachment_fields_to_edit
and attachment_fields_to_save
.
I’m going to provide two examples that I use often: adding a “Photo credit” section, and adding an “Include in Rotator” selection.
Adding Photo Credit
You’ll often need to provide attribution to the source of images you use on your website. Rather than sticking it at the top or bottom of the post, we can add that information as photo metadata and then include it in the theme.
I’m going to add two text fields, Photographer Name and Photographer URL.
<?php | |
/** | |
* Add Photographer Name and URL fields to media uploader | |
* | |
* @param $form_fields array, fields to include in attachment form | |
* @param $post object, attachment record in database | |
* @return $form_fields, modified form fields | |
*/ | |
function be_attachment_field_credit( $form_fields, $post ) { | |
$form_fields['be-photographer-name'] = array( | |
'label' => 'Photographer Name', | |
'input' => 'text', | |
'value' => get_post_meta( $post->ID, 'be_photographer_name', true ), | |
'helps' => 'If provided, photo credit will be displayed', | |
); | |
$form_fields['be-photographer-url'] = array( | |
'label' => 'Photographer URL', | |
'input' => 'text', | |
'value' => get_post_meta( $post->ID, 'be_photographer_url', true ), | |
'helps' => 'If provided, photographer name will link here', | |
); | |
return $form_fields; | |
} | |
add_filter( 'attachment_fields_to_edit', 'be_attachment_field_credit', 10, 2 ); | |
/** | |
* Save values of Photographer Name and URL in media uploader | |
* | |
* @param $post array, the post data for database | |
* @param $attachment array, attachment fields from $_POST form | |
* @return $post array, modified post data | |
*/ | |
function be_attachment_field_credit_save( $post, $attachment ) { | |
if( isset( $attachment['be-photographer-name'] ) ) | |
update_post_meta( $post['ID'], 'be_photographer_name', $attachment['be-photographer-name'] ); | |
if( isset( $attachment['be-photographer-url'] ) ) | |
update_post_meta( $post['ID'], 'be_photographer_url', $attachment['be-photographer-url'] ); | |
return $post; | |
} | |
add_filter( 'attachment_fields_to_save', 'be_attachment_field_credit_save', 10, 2 ); |
In the first function we used a simple array to specify the field’s Label, input type, value, and help text. In the second function, we check to see if a value has been set for those fields, and if so we update the post metadata.
To access this information in our theme, we simply have to get the post meta for the thumbnail. Assuming we want it for the featured image, we’d do something like this: get_post_meta( get_post_thumbnail_id(), 'be_photographer_name', true );
Include in Rotator
Adding text fields is rather easy. What if you want something more custom? If you use the ‘html’ input type, you can output whatever HTML you’d like.
I love using the built-in Gallery feature in WordPress for managing image rotators on specific posts or pages. The problem is that all images are included in the gallery. So I add an “Include in Rotator” option when editing the image, and then I can query for all attached images that were marked “Yes”.
For more examples of creating html inputs for the media gallery, look in /wp-admin/includes/media.php.
<?php | |
/** | |
* Add "Include in Rotator" option to media uploader | |
* Limited to Home page | |
* | |
* @param $form_fields array, fields to include in attachment form | |
* @param $post object, attachment record in database | |
* @return $form_fields, modified form fields | |
*/ | |
function be_attachment_field_rotator( $form_fields, $post ) { | |
// // Only show on front page | |
if( ! ( $post->post_parent == get_option( 'page_on_front' ) ) ) | |
return $form_fields; | |
// Set up options | |
$options = array( '1' => 'Yes', '0' => 'No' ); | |
// Get currently selected value | |
$selected = get_post_meta( $post->ID, 'be_rotator_include', true ); | |
// If no selected value, default to 'No' | |
if( !isset( $selected ) ) | |
$selected = '0'; | |
// Display each option | |
foreach ( $options as $value => $label ) { | |
$checked = ''; | |
$css_id = 'rotator-include-option-' . $value; | |
if ( $selected == $value ) { | |
$checked = " checked='checked'"; | |
} | |
$html = "<div class='rotator-include-option'><input type='radio' name='attachments[$post->ID][be-rotator-include]' id='{$css_id}' value='{$value}'$checked />"; | |
$html .= "<label for='{$css_id}'>$label</label>"; | |
$html .= '</div>'; | |
$out[] = $html; | |
} | |
// Construct the form field | |
$form_fields['be-include-rotator'] = array( | |
'label' => 'Include in Rotator', | |
'input' => 'html', | |
'html' => join("\n", $out), | |
); | |
// Return all form fields | |
return $form_fields; | |
} | |
add_filter( 'attachment_fields_to_edit', 'be_attachment_field_rotator', 10, 2 ); | |
/** | |
* Save value of "Include in Rotator" selection in media uploader | |
* | |
* @param $post array, the post data for database | |
* @param $attachment array, attachment fields from $_POST form | |
* @return $post array, modified post data | |
*/ | |
function be_attachment_field_rotator_save( $post, $attachment ) { | |
if( isset( $attachment['be-rotator-include'] ) ) | |
update_post_meta( $post['ID'], 'be_rotator_include', $attachment['be-rotator-include'] ); | |
return $post; | |
} | |
add_filter( 'attachment_fields_to_save', 'be_attachment_field_rotator_save', 10, 2 ); |
Then when I want to get all the attached images that are going in the rotator, I run something like this:
<?php | |
// Get all images attached to post that have "Include in Rotator" marked as "Yes" | |
global $post; | |
$args = array( | |
'post_parent' => $post->ID, | |
'post_type' => 'attachment', | |
'post_mime_type' => 'image', | |
'post_status' => 'inherit', | |
'posts_per_page' => '-1', | |
'order' => 'ASC', | |
'orderby' => 'menu_order', | |
'meta_query' => array( | |
array( | |
'key' => 'be_rotator_include', | |
'value' => '1' | |
) | |
) | |
); | |
$images = new WP_Query( $args ); | |
if( !$images->have_posts() ) | |
return; | |
while( $images->have_posts() ): $images->the_post(); global $post; | |
// Echo image url | |
$image = wp_get_attachment_image_src( $post->ID, 'be_featured' ); | |
echo $image[0] . '<br />'; | |
endwhile; wp_reset_query(); |
peter says
hi Bill,
Your code has worked fine for me in the past, but seems broken in wordpress 3.5. I am trying it out in my local development environment so dont have a website example to give you, but this is understandable given that 3.5 has changed things regarding attachments – is there code that works with 3.5 yet? I have googled everywhere but no one seems to have any answers yet. Cheers.
Bill Erickson says
Correct, this tutorial does not work with the new media uploader. I’ve marked this post as old since the code doesn’t work, and included a link to a tutorial describing how to customize the 3.5 editor.
hans says
Strange, because it works for me in 4.3. used exactly your code …
Matthias says
Still works like a charme for 5.7.2. Thank you!