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(); |
Jared says
Awesome tip, especially useful when it comes to the photo credits/links!
Remkus says
Nice one Bill. Thanks:)
Jan says
Wow. Really awesome stuff and not least a very usable tip. Thanks a lot.
Great site. Bookmarked!
Murfreesboro TN says
Great tip!! Thanks Bill, I appreciate you posting this, really helped me out.
– John
Kostya says
Hey Bill! Thank you for the tip. I was trying to implement your code and found a typo which caused an error. You missed the letter ‘S’ in add_filter( ‘attachment_field_to_save’, ‘be_attachment_field_credit_save’, 10, 2 ). The name of the filter to hook should be ‘attachment_fields_to_save’.
Bill Erickson says
Good catch! I’ve updated the code.
Bob Patterson says
Thanks for the tip Bill. This will save a lot of time.
BTW I bought Driskill last night. Very nice. I planned to make something similar for one of my sites but buying yours was much ea
Bob Patterson says
This may be a duplicate. My iPad is acting a little wonky.
Thanks for the tips here. They will save a lot of time and hassle.
Also, thought I mention that I bought Driskill last night. Very nice and just what I needed. I was planning to make something similar for one of my sites. Buying your theme was much easier and faster. The responsive design was icing on the cake.
Bob
Luke says
This is awesome! Is there a way to limit the fields to a specific mime type? For example, add fields that have a mime type of ‘video’ and not to ‘images’?
Bill Erickson says
That’s a great question. I’ve never tried that. I recommend looking at the $post object to see if it has the mime type in it, or you can do
$mime = get_post_mime_type( $post->ID );
More info: http://codex.wordpress.org/Function_Reference/get_post_mime_type
Luke says
Sweet, thanks! Actually, I just figured it out of I posted. In this case it was for audio, in which I though ‘audio’ would work, but had to use ‘audio/mpeg’ when get post mime type.
$post_mime_type = ( 'audio/mpeg' == get_post_mime_type( $post ) ) ? 1 : 0;
Then I just did an simple if statement in be_attachment_field_credit().
if( 1 == $post_mime_type ) {
$form_fields[...] = array(...);
}
It seems to then show the fields on audio/mpeg type files, and not an images/video or other mime types.
Great post!
Luke says
I need to proofread before submitting… arr.
satishraj says
Thanks Bill Erickson this helped me to solve my problem, as i want to display my customized fields and make some validations on the media.php file so that it could validate the media form………
i made the changes in _save method it resolved…
thanks alot again