Saving ‘meta data’ for WordPress categories

By michael  |  February 7th, 2010  |  Published in Development, WordPress  |  15 Comments

[updated 2010-06-08]

WordPress has some great hooks for adding extra fields to the Add Category page (as well as the edit category and the table listing the categories). Where / how do you save that data though. I ran accross a couple other devs on Twitter this evening that were asking this question. This post is primarily for them and it doesn’t provide all the code you need to get finish, but it should get most dev on their way. For instance, you will need another action for adding to the edit page, another action for adding to the table, and another action for editing the data. You will need to replace the type of fields. The below code assumes a custom taxonomy called ‘manufacturers’.

Additionally, the code below saves every field for every category or taxonomy in a different line in the options table. If I were going to put this into production I’d serialize the data so that all fields for a single category were stored in a single row of the options table.

Finally, as this is not in production yet (though it has been tested) there may be some errors or bugs. Please let me know if you find any and I will update (code would be nice too).

This following code, placed in your theme’s functions.php file:

<?php
### CUSTOM FIELDS FOR MANUFACTURERS

	// Manufacturer fields
	function ft_add_manufacturer_fields(){
		?>
		<!-- Web Site -->
		<div class="form-field">
			<label for="man_web_site"><?php _e('Manufacturer Web Site') ?></label>
			<input type='text' name="man_web_site" id="man_web_site" />
			<p><?php _e('The manufacturer\'s web site.'); ?></p>
		</div>

		<!-- Logo -->
		<div class="form-field">
			<label for="man_logo_url"><?php _e('Manufacturer Logo URL') ?></label>
			<input type='text' name="man_logo_url" id="man_logo_url" />
			<p><?php _e('The web address of the manufacturer\'s logo.'); ?></p>
		</div>

		<!-- Status -->
		<div class="form-field">
			<label for="man_status"><?php _e('Manufacturer Status') ?></label>
			<select name="man_status" id="man_status"><option value='standard' selected="selected">Standard</option><option value='premium'>Premium</option></select>
			<p><?php _e('Only manufacturer\'s with a premium status will have their logos linked to their web site.'); ?></p>
		</div>

		<?php
	}
	add_action('manufacturers_add_form_fields','ft_add_manufacturer_fields');

	// Add field to edit category screen
	function ft_edit_manufacturers_form(){	

		// clear values.
		$man_web_site = $man_logo_url = $man_status = '';

		// Clean tag id
		$id = sanitize_text_field($_GET['tag_ID']);

		if ( $opt_array = get_option('man_'.$id.'_meta') ){
			$man_web_site 	= sanitize_text_field($opt_array['man_web_site']);
			$man_logo_url 	= sanitize_text_field($opt_array['man_logo_url']);
			$man_status 	= sanitize_text_field($opt_array['man_status']);
		}
		?>
		<!-- Web Site -->
		<tr class="form-field">
			<th scope="row" valign="top"><label for="man_web_site"><?php _e('Manufacturer Web Site') ?></label></th>
			<td><input type='text' name="man_web_site" id="man_web_site" value="<?php echo $man_web_site; ?>" /><br />
			<span class="man_web_site"><?php _e('The manufacturer\'s web site.'); ?></span></td>
		</tr>

		<!-- Logo -->
		<tr class="form-field">
			<th scope="row" valign="top"><label for="man_logo_url"><?php _e('Manufacturer Logo URL') ?></label></th>
			<td><input type='text' name="man_logo_url" id="man_logo_url" value="<?php echo $man_logo_url; ?>" /><br />
			<span class="man_logo_url"><?php _e('The URL for the manufacturer\'s logo.'); ?></span></td>
		</tr>

		<!-- Status -->
		<tr class="form-field">
			<th scope="row" valign="top"><label for="man_status"><?php _e('Manufacturer Status') ?></label></th>
			<td><select name="man_status" id="man_status"><option value='standard' selected="selected">Standard</option><option value='premium' <?php if ( $man_status == 'premium' ){ echo 'selected="selected" '; } ?>>Premium</option></select>
			<br /><span class="man_status"><?php _e('Only manufacturer\'s with a premium status will have their logos linked to their web site.'); ?></span></td>
		</tr>

		<?php
	}
	add_action('manufacturers_edit_form_fields','ft_edit_manufacturers_form');

	// Add Manufacturer fields to table head
	function ft_manage_manufacturers_columns($columns){
		if ( !isset($_GET['taxonomy']) || $_GET['taxonomy'] != 'manufacturers' )
			return $columns;

		if ( $posts = $columns['posts'] ){ unset($columns['posts']); }
		$columns['man_status'] = 'Status';
		if ( isset($posts) ){ $columns['posts'] = 'Machines'; }
		return $columns;
	}
	add_filter('manage_edit-tags_columns','ft_manage_manufacturers_columns');

	// Add fields to table for each manufacturer
	function ft_manage_manufacturers_custom_fields($deprecated,$column_name,$term_id){
		if ( $opt_array = get_option('man_'.$term_id.'_meta') ){
			return esc_html($opt_array[$column_name]);
		}
	}
	add_filter('manage_manufacturers_custom_column','ft_manage_manufacturers_custom_fields',10,3);

	// Insert or Update the Manufacturer
	function ft_create_update_manufacturer($term_id,$tt_id){
		// Grab your field names in $_POST, sanatize and put wherever you want
		if ( isset($_POST['man_web_site']) )
			$update['man_web_site'] = sanitize_text_field($_POST['man_web_site']);
		if ( isset($_POST['man_logo_url']) )
			$update['man_logo_url'] = sanitize_text_field($_POST['man_logo_url']);
		if ( isset($_POST['man_status']) )
			$update['man_status'] = sanitize_text_field($_POST['man_status']);

		if ( isset($update) )
			update_option( 'man_'.$term_id.'_meta' , $update );

	}
	add_action('created_manufacturers','ft_create_update_manufacturer',10,2);
	add_action('edit_manufacturers','ft_create_update_manufacturer',10,2);

	// On Delete Manufacturer
	function ft_delete_manufacturer($term_id,$tt_id){
		delete_option('man_'.$term_id.'_meta');
	}
	add_action('delete_manufacturers','ft_delete_manufacturer',10,2);
>

Download a text file with the above code: here

Responses

  1. BMM Web Design Bucur says:

    March 17th, 2010 at 1:30 pm (#)

    I've just started using WordPress. I can take all the help I can get. Thanks for the post!

  2. Jonas says:

    May 16th, 2010 at 10:23 pm (#)

    Just what I'm looking for ;-D

    Is it also posible to position the extra field above the save button, under description?

    Thanks in advance

  3. shawn says:

    May 28th, 2010 at 8:19 pm (#)

    Wow this is a great starting article!

    I’m not really a developer but am learning the ins and outs of wp. After hunting around to figure out how to add category image metaboxes, somehow I stumbled upon this article.

    I really look forward to your updated article on this concept. This is going to open so many doors for me.

    Thank you so much!

  4. Glenn Ansley says:

    May 28th, 2010 at 9:21 pm (#)

    I actually have some significantly updated code. I’ll try to post it after the holiday.

  5. Glenn Ansley says:

    June 11th, 2010 at 4:22 am (#)

    Hey – Thanks. Yep, you've got the latest. Let me know if you have any questions / updates.

  6. illimar says:

    June 11th, 2010 at 8:07 am (#)

    Hey, this is really a good bit of code. Have You updated it yet?

  7. shawn says:

    June 11th, 2010 at 5:52 pm (#)

    Thank you for the updated code.

    By any chance have you had to extend this for client sites in the post_type UI?

    What I mean is I'm guessing you are using this with a post_type, where when adding a new 'product' the admin would select an existing 'manufacturer' taxonomy from the select box, kind of exactly how we add categories to posts.

    I've been working on the scenario of what happens when adding a new post-type 'product' if the 'manufacturer' taxonomy term does not exist yet. Currently we only have the ability to add the term, but not the custom fields belonging to the term from the post-type UI.

    This forces the user to leave the post-type UI, and then go to the term UI to add in the extra fields.

    To date I have not seen anyone attempting to do this yet. It just seems like a logical step to make life easier on the user inputting the new 'product', to be able to add a term + term custom fields, within the add post UI.

    Either way, thank you, this is a great start for me.

  8. Glenn Ansley says:

    June 11th, 2010 at 10:44 pm (#)

    Hi Shawn,
    Are you talking about adding custom fields from the write / edit (custom) post page when creating category / taxonomy terms on the fly?

    If so, this isn’t something I’ve looked at yet. It would probably be a GUI nightmare to attempt this but I’ll look to see if the hooks are in place to make it possible.

  9. shawn says:

    June 12th, 2010 at 3:04 pm (#)

    @Glenn
    Yes, that is exactly what I am trying to describe.

    I was doing a demo for a friend and it became quickly apparent to me that he was not understanding the concept of having to add taxonomy metadata on a separate screen if he was adding a new term.

    That got me thinking about the entire UX with the new tools that wp is giving us. It seemed like a natural progression to allow editing within one primary screen of all needed input information. Obviously not necessary, but it does help make wp more user-friendly.

    I was thinking of using a lightbox or modal window pop up for adding in the new data. Anyhow, mostly just a concept right now.

  10. Glenn Ansley says:

    June 15th, 2010 at 4:06 am (#)

    Yes, it can. The above example actually assumes a custom tax called manufacturers.

  11. Johannes Holmberg says:

    June 15th, 2010 at 7:30 am (#)

    Hi!

    I want to know if I can append this to custom taxonomies in WordPress 3?

  12. Johannes Holmberg says:

    June 16th, 2010 at 9:03 am (#)

    Okay nice!

    Thought it was just for original categories at first.
    But how do I get these values from the theme?

  13. Simon says:

    September 17th, 2010 at 2:03 pm (#)

    This is really helpful code, it's saved me a lot of time digging through core figuring it all out myself.

    Do you think that ideally it would be preferable to add columns to the term_taxonomy table, rather than using the options table for the custom fields?

    It would seem to make sense to me logically (your custom fields are stored in the same place as the description, slug, etc.), but maybe there is a downside I haven't thought of…

  14. Glenn Ansley says:

    September 22nd, 2010 at 4:16 am (#)

    @simon – I've considered several places to store the data. I think this is the best solution for now. I'd rather use the options API (that's what it was built for) than adding additional columns to core WP tables.

  15. WordPress: How to change the Edit Category / Taxonomy admin panel | Dan Smart - Web Developer says:

    April 29th, 2013 at 3:39 am (#)

    [...] data stored with each category (maybe using the Category Meta plugin, or a method somewhat like on this post), or perhaps you wish to display another piece of data to the [...]