Plugin To Add Custom Field To An Attachment In WordPress

5 Day
The media library is on WordPress in some areas, certainly not perfect, but it has great potential. Each attachment can contain various metadata and also WordPress stores some data directly while uploading – for example a part of the Exif data of an image.

However, it might not be enough for you and you need some additional custom data with the attachment, whether in order to control something in the backend of WordPress, or even display the data in the front end to the image. So here is a small tutorial how to add an additional field. You can use this solution directly and adding a new field with the help of a Plugin.

For the output of the data I present a simple method that can be adjusted accordingly. To read the data, which is assigned to the attachment, there are many functions provided by WordPress and enables you to realize so many amazing things – depending on knowledge and skills of the developer – such as related articles.

The above screenshot shows what we are aim for. An additional field with the name Example Custom Field, also an input field and a description below the field.

Add the Custom Field

First we create a function, which outputs the 3 new fields in the attachment area. These fields are getting delivered in an array and then via the according hook attachment_fields_to_edit integrated in WordPress.

// Add a custom field to an attachment in WordPress
function fb_attachment_fields_edit($form_fields, $post) {
	
	$form_fields['custom_example']['label'] = __( 'Example Custom Field', FB_AAF_TEXTDOMAIN );
	$form_fields['custom_example']['value'] = get_post_meta($post->ID, '_custom_example', true);
	$form_fields['custom_example']['helps'] = __( 'A helpful text for this field.', FB_AAF_TEXTDOMAIN );
	
	return $form_fields;
}

Save the custom values

Now that we have completed the data fields, we must take care about saving the values. For this case WordPress provides the hook attachment_fields_to_save, so that you only need to hook in the memory function.

// save custom field to post_meta
function fb_attachment_fields_save($post, $attachment) {
	
	if ( isset($attachment['custom_example']) )
		update_post_meta($post['ID'], '_custom_example', $attachment['custom_example']);
	
	return $post;
}

Hook to work in WordPress

The two functions, explained before, providing the necessary functions and now we are going to integrate it into WordPress. Here a short explanation with the help of these two filter hooks. In both cases, our functions passing two parameters to the hooks of WordPress and they are passed with the default value of priority 10. Everything goes through one filter in WordPress and therefore to hook on the respective Filter-Hook (add_filter) attachment_fields_to_*. The transfer via array array(&$this, ... takes place here only because everything is used in connection within a class.

add_filter( 'attachment_fields_to_edit', array(&$this, 'fb_attachment_fields_edit'), 10, 2);
add_filter( 'attachment_fields_to_save', array(&$this, 'fb_attachment_fields_save'), 10, 2);

The Example Plugin

Now we incorporate the functions and their hooks in a Plugin and we can simple use the additional functions inside of WordPress. I think the separation of additional functions in Theme and Plugin is very important because the priority of integration is different and because from my point of view function expansions in a Theme are useful only if they are just additional functions for the Theme and not for WordPress.
Also the use via class is useful, because of a cleaner code. But there are enough articles about the benefits of object-oriented programming and the usage of classes.

= 2.7 and tested with PHP Interpreter >= 5.2.9
*/

//avoid direct calls to this file, because now WP core and framework has been used
if ( !function_exists('add_action') ) {
	header('Status: 403 Forbidden');
	header('HTTP/1.1 403 Forbidden');
	exit();
} elseif ( version_compare(phpversion(), '5.0.0', '<') ) {
	$exit_msg = 'The plugin require PHP 5 or higher';
	header('Status: 403 Forbidden');
	header('HTTP/1.1 403 Forbidden');
	exit($exit_msg);
}


if ( !class_exists('add_attachment_fields') ) {
	
	//WordPress definitions
	if ( !defined('WP_CONTENT_URL') )
		define('WP_CONTENT_URL', get_option('siteurl') . '/wp-content');
	if ( !defined('WP_CONTENT_DIR') )
		define('WP_CONTENT_DIR', ABSPATH . 'wp-content');
	if ( !defined('WP_PLUGIN_URL') )
		define('WP_PLUGIN_URL', WP_CONTENT_URL.'/plugins');
	if ( !defined('WP_PLUGIN_DIR') )
		define('WP_PLUGIN_DIR', WP_CONTENT_DIR.'/plugins');
	if ( !defined('PLUGINDIR') )
		define( 'PLUGINDIR', 'wp-content/plugins' ); // Relative to ABSPATH.  For back compat.
	if ( !defined('WP_LANG_DIR') )
		define('WP_LANG_DIR', WP_CONTENT_DIR . '/languages');
	
	// plugin definitions
	define( 'FB_AAF_BASENAME', plugin_basename(__FILE__) );
	define( 'FB_AAF_BASEDIR', dirname( plugin_basename(__FILE__) ) );
	define( 'FB_AAF_TEXTDOMAIN', 'add_attachment_fields' );
	
	class add_attachment_fields {
		
		function __construct() {
			
			if ( !is_admin() )
				return FALSE;
				
			add_action( 'init', array(&$this, 'text_domain') );
			add_filter( 'attachment_fields_to_edit', array(&$this, 'fb_attachment_fields_edit'), 10, 2);
			add_filter( 'attachment_fields_to_save', array(&$this, 'fb_attachment_fields_save'), 10, 2);
		}
		
		function text_domain() {
			
			load_plugin_textdomain( FB_AAF_TEXTDOMAIN, false, FB_AAF_BASEDIR . '/languages' );
		}
		
		// Add a custom field to an attachment in WordPress
		function fb_attachment_fields_edit($form_fields, $post) {
			
			$form_fields['custom_example']['label'] = __( 'Example Custom Field', FB_AAF_TEXTDOMAIN );
			$form_fields['custom_example']['value'] = get_post_meta($post->ID, '_custom_example', true);
			$form_fields['custom_example']['helps'] = __( 'A helpful text for this field.', FB_AAF_TEXTDOMAIN );
			
			return $form_fields;
		}
		
		// save custom field to post_meta
		function fb_attachment_fields_save($post, $attachment) {
			
			if ( isset($attachment['custom_example']) )
				update_post_meta($post['ID'], '_custom_example', $attachment['custom_example']);
			
			return $post;
		}
		
	}
	
	function add_attachment_fields_start() {
	
		new add_attachment_fields();
	}
	
	add_action( 'plugins_loaded', 'add_attachment_fields_start' );
}
?>

Example to use the values on Frontend or Plugins

Additional to the Plugin, I have a small solution to output the meta data of the attachment. But I also recommend to read the previously mentioned article, as you can get far more information there.

$attachments = get_children( array(
		'post_parent'    => get_the_ID(),
		'post_type'      => 'attachment',
		'numberposts'    => 1, // show all -1
		'post_status'    => 'inherit',
		'post_mime_type' => 'image',
		'order'          => 'ASC',
		'orderby'        => 'menu_order ASC'
	) );
foreach ( $attachments as $attachment_id => $attachment ) {
	echo get_post_meta($attachment_id, '_custom_example', true);
}

A practical example – photographer and its URL – has been recently posted by Thomas Scholz on WordPress Answers. A nice usage for this possibility.


Posted

in

,

by

Comments

8 responses to “Plugin To Add Custom Field To An Attachment In WordPress”

  1. Julian Avatar
    Julian

    Great!
    Is there a way to add a checkbox-input?

    Thanks a lot

  2. Frank Avatar

    @Julian: yes, you can also add checkboxes, all html-formular-fields

  3. Michael Avatar

    @Towfiq I.: Thanks! It’s fixed now.

  4. Jon Avatar
    Jon

    Very useful – thanks. Is there a way to make this field searchable within media library “search media” without hacking core?

  5. Mark Avatar

    Thanks Frank, very useful, it helped me create a plugin that allowed me to create multiple galleries in the same post.

  6. Milan Avatar

    One related question: do you have an idea for a code that will show fields for attachment only on screen for attachment edit (got on Media screen) and not on popup screen in Add * on new post page?

    attachment_fields_to_edit will show fields on both places.

  7. Thomas Avatar
    Thomas

    Ehm…is there any way to copy the clean and plain source PHP code on this page?