Since WordPress 2.9, support has been added for term or taxonomy meta-data. The relevant functions are in wp-includes/meta.php and they include –
- add_metadata($meta_type, $object_id, $meta_key, $meta_value, $unique = false)
- update_metadata($meta_type, $object_id, $meta_key, $meta_value, $prev_value = ”)
- delete_metadata($meta_type, $object_id, $meta_key, $meta_value = ”, $delete_all = false)
- get_metadata($meta_type, $object_id, $meta_key = ”, $single = false)
These functions are similar to the add_post_meta, update_post_meta, delete_post_meta, and get_post_meta functions that allow us to add meta data to post objects.
The generalized functions above will allow you to add meta data to any object type (including tags, categories, and any taxonomy object), as long as you create a relevant database table to store the information.
1. Meta-Data Type
First, we must decide what object type we want to assign meta-data to.
For example –
- Post meta-data has type = post,
- Comment meta-data has type = comment,
and so forth.
Here, we want to add meta-data to taxonomy objects, therefore we will set our
type = shiba_term.
2. Create a Taxonomy Table
Now, we must create a table to store the meta-data for our taxonomy objects. Meta-data tables should contain at least 4 columns with the following names –
- meta_id – Contains the unique id of each piece of meta-data information that is stored in our taxonomy meta-data table.
- {$type}_id – Contains the unique id of the object to associate with the given meta-data. In this article, our $type = shiba_term, therefore this column will be called shiba_term_id.
- meta_key – Meta-data key.
- meta_value – Meta-data value.
// create table in your plugin activation function function create_metadata_table($table_name, $type) { global $wpdb; if (!empty ($wpdb->charset)) $charset_collate = "DEFAULT CHARACTER SET {$wpdb->charset}"; if (!empty ($wpdb->collate)) $charset_collate .= " COLLATE {$wpdb->collate}"; $sql = "CREATE TABLE IF NOT EXISTS {$table_name} ( meta_id bigint(20) NOT NULL AUTO_INCREMENT, {$type}_id bigint(20) NOT NULL default 0, meta_key varchar(255) DEFAULT NULL, meta_value longtext DEFAULT NULL, UNIQUE KEY meta_id (meta_id) ) {$charset_collate};"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); }
We can set our table name to anything we want, but it is best to follow WordPress convention and name our taxonomy table as follows
global $wpdb; $table_name = $wpdb->prefix . $type . 'meta';
Therefore, our table name in this example is wp_shiba_termmeta.
3. Register Taxonomy Table
To enable the WordPress metadata functions, we must also register our new table.
// Add to your plugin init function global $wpdb; $variable_name = $type . 'meta'; $wpdb->$variable_name = $table_name;
In particular, the meta-data functions will look for our table name in the variable –
$type . ‘meta’ within the $wpdb global object. Therefore, it is important to initialize this value correctly as we have shown above.
Since our $type = shiba_term, our table registration statement will look like this –
$wpdb->shiba_termmeta = $wpdb->prefix . 'shiba_termmeta'
We are Done!
And just like that, we are all done. We can now add meta-data values to any taxonomy object. For example, suppose to want to add some meta-data into our WordPress tags.
<?php // Add to your plugin admin_init function add_action ( 'edit_tag_form_fields', 'tag_input_metabox' ); add_action ( 'edited_terms', 'save_tag_data' ); function tag_input_metabox($tag) { $selected = get_metadata('shiba_term', $tag->term_id, 'new_metadata', TRUE); ?> <tr class="form-field"> <th scope="row" valign="top"><label for="tag_widget"><?php _e('New Input') ?></label></th> <td> <select name='tag_meta_input' id='tag_meta_input'> <!-- Display all our meta-data options --> </select> </td> </tr> <?php } function save_tag_data($term_id) { if (isset($_POST['tag_meta_input'])) { $tag_metadata = esc_attr($_POST['tag_meta_input']); update_metadata('shiba_term', $term_id, 'new_metadata', $tag_metadata); } } ?>
tag_input_metabox adds a new input form to our WordPress Tag Edit screen. The input results are saved in the tag_meta_input field.
save_tag_data retrieves the input data from our new tag_meta_input field, and saves it to our tag object.
Jeff Rose says
Hi Folks. This is an awesome tutorial I found a day to late.
The downside here is creating that new table. In 2.9 we didn’t have any other options, but now in 3.0+ you can accomplish it with a custom post type.
The code in this pastebin is an EXAMPLE and hasn’t been thoroughly tested.
http://pastebin.com/zYy6PePz
Feedback is appreciated.
Manny Fleurmond says
Hi! Thanks for the code examples, but I was wondering how you can set it so that the metabox only appears under certain taxonomies and not all of them?
ShibaShake says
Instead of using the edit_tag_form_fields action hook, use the specific taxonomy action hook instead.
cooljaz124 says
Hey Shiba ! Great work.
Can you let me know how can we achieve the same thing with category ??
Also, it could have been great if you have posted the screenshot of tags meta in dashboard.
Thanks
Jaz
ShibaShake says
Just use the category term_id.
Check out Dashboard Widgets API.
Anthony says
Great information! Now, please excuse the newbishness… I want to use this method in my own theme and have some questions. I can see that shiba-meta.php and shiba-theme-metabox.php are not “drag-n-drop” ready. Can you comment on what terms and variables used in those files have external dependencies? The use of the term ‘theme’ through out the files has me a bit confused. For example:
update_post_meta( $post_id, ‘theme’, $theme_id);
‘theme’ is used as $meta_key but I can’t seem to find where that key was defined. Also, can you explain your use of global $shiba_theme?
Thank you for the great information, and thank you in advance for your response!
ShibaShake says
‘theme’ is just the name of the custom field and does not need to be separately defined, e.g. the name ‘new_metadata’ in the example above. Check out get_post_meta and update_post_meta.
It may be easiest to just follow the tutorial above rather than try to decode the files used in Shiba Theme. Shiba Theme contains a lot of other features and separating out the parts that you need may be more work than starting from a clean slate.
Anthony says
I realized (again) why I should NOT try coding late in the evening. I get all cross eyed and make really dumb mistakes. But anyway… I am wondering now where you came up with the action hooks you are using:
add_action ( ‘edit_tag_form_fields’, ‘tag_widget_metabox’ );
add_action ( ‘edited_terms’, ‘save_tag_data’ );
There seems to be no documentation on them in the codex. Also, you suggested I look at the post_meta functions. I don’t understand the reason for that since we are not working with $post meta data, but rather $tag or $term meta data. Even in your example there is no use of get_post_meta(), but rather get_metadata(). And of course there is little documentation on those functions…
ShibaShake says
I usually find the proper hooks by looking at the WordPress source code. For example, if I need to add something to the Media Edit screen, I start by looking at that file and then follow related functions until I find the appropriate hooks.
I only suggested looking at post_meta because you asked –
I was not sure if you were interested in adding meta-data to posts, terms, or both.
Michael Fields says
Perfect! This is great to find as I had no idea that this was even possible. Thanks for posting.
Rafael Dourado says
You could have used the action ‘edited_shiba_term’ instead of ‘edited_terms’.
And you could also have used ‘shiba_term_add_form_fields’ and ‘create_shiba_term’ actions to add the new field to Add Taxonomy screen.
Diane says
How do you add metadata to WordPress sites that are not hosted by me if I can’t add plugins? Can you give specific directions if this is possible?
ShibaShake says
This will only work for self-hosted WordPress sites.
James Lafferty says
Nice tutorial… it definitely got me looking around in the right places to get stuff done. I actually wound up needing to call $wpdb->query() from my function to create the table, though, which from the looks of it isn’t fantastic practice. Would you be able to elaborate at all on the drawbacks of using $wpdb->query() rather than dbDelta() here, if that’s not just too insanely geeky. From what I can tell the biggest issue is if I want to modify my schema at some future date, dbDelta() would better position me to handle that.
ShibaShake says
Truthfully, I only used dbDelta because that was used in the WordPress Codex example.
I looked at the dbDelta function briefly and it seems that it can be used to execute multiple creation and insertion queries. I think the main advantage is that it can be used to modify the structure of existing tables.
It also does more validation in terms of checking for global tables, etc.
However, there were also some open tickets on it, and I have had some people reporting plugin bugs that may be the result of dbDelta not working properly on their server setup. What happened when you used dbDelta? What error did it return?
James Lafferty says
Jeez, I feel lame for not replying, and at this point, I can’t remember what error it returned. I’ll see if I can backtrack and figure out what went wrong. Again, love your take on things WP.
James Lafferty says
Having had a second look, it seems like I had an issue with ‘require_once(ABSPATH . ‘wp-admin/includes/upgrade.php’);’ — mostly it was a flow thing, but I was also concerned about potentially doing that include a lot, as I was trying to create the table only if there was term metadata specified elsewhere… A little convoluted as a reply, I know, but the gist of it is that I didn’t have an error, just didn’t want to load upgrade.php all the time.]
Cheers!
ShibaShake says
Thanks for getting back to me James. This definitely helps. 😀
James Lafferty says
Just wanted to let you know that your blog definitely in part inpired me to write my Term Menu Order Plugin (released just today). The other inspiration was that I needed the functionality for a site I was working on.
The key insight I got from your blog was looking at terms as potentially the same as posts in ways that could be surprising (i.e., the termmeta table you use here inspired me to consider simply adding a menu_order column to the terms table).
As a point of relevance to this particular thread, dbDelta didn’t work for this either, as it filters out ALTER TABLE queries (looks like it only accepts CREATE TABLE, CREATE DATABASE, INSERT and UPDATE).
ShibaShake says
Hi James,
Congratulations on your new plugin release and thanks for your comment. I will definitely check your plugin out. I truly enjoy this side of the WP community – the sharing of ideas, code, and encouragement.
Merry Christmas and Happy Holidays!
Modesty says
ShibaShake,
can I paste all of this in to my functions.php or does it have to be a plugin? what would be the final version of the whole code together?
many tnx
m
ShibaShake says
I wouldn’t recommend doing this unless you are comfortable with PHP and database operations.
The code involves creating a table, which means writing to your database and you don’t want to do that unless you totally understand the code and are comfortable with basic database manipulation on your server. Otherwise, you may end up corrupting your database.
If you want a full example of the code the Shiba Theme, Shiba Background plugin, and Shiba Widgets plugin all use it.
Table creation is in shiba-meta.php and some examples of update_post_meta and delete_post_meta are in shiba-*-metabox.php.
Remember to backup your database first just to be safe.
Francisco says
Great tutorial! This is exactly what I was looking for.
Thank you!