aaf-wp

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.

<?php
/**
 * @package Add Attachment Fields
 * @author Frank Bültge
 */

/*
Plugin Name: Add Attachment Fields
Plugin URI: http://bueltge.de/
Text Domain: add_attachment_fields
Domain Path: /languages
Description: Example for add a custom field to an attachment in WordPress
Author: Frank Bültge
Version: 0.0.1
Author URI: http://bueltge.de/
Donate URI: http://bueltge.de/wunschliste/
License: GPL
Last change: 24.11.2010 10:21:19
*/ 

/**
License:
==============================================================================
Copyright 2009/2010 Frank Bueltge  (email : frank@bueltge.de)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Requirements:
==============================================================================
This plugin requires WordPress >= 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.

Comments are closed.

8 comments

  1. Julian

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

    Thanks a lot

  2. Frank

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

  3. Towfiq I.

    The related article link is broken:
    http://wpengineer.com/1735%20/%20shows%20easier-better-solutions-to-get-pictures-on-your-posts/

  4. Michael

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

  5. Jon

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

  6. Mark

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

  7. Milan

    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.

  8. Thomas

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