This is going to be a ton of code and a ton of explanation. Most of which can be copy and paste but I suggest taking the time to understand what’s going on and why. First thing to understand is that WordPress does not have Taxonomy Metadata but it may someday. This means that we need to save our data as options. Second thing to understand is that we have to deal with multiple hooks:
- {$taxonomy}_add_form_fields – The page where we add the terms.
- {$taxonomy}_edit_form_fields – Whenever a user clicks the term to edit the slug or description once it’s been created.
- created_{$taxonomy} – Save the data whenever a taxonomy term is created.
- edited_{$taxonomy} – Save the data whenever a taxonomy term is modified / edited.
- pre_delete_term – To clean up our data whenever a term is deleted.
Whenever you see {$taxonomy} you would replace it with whatever you taxonomy slug is. In this example I will use the default / built-in Post Categories taxonomy whose slug is category
.
The below will not cover adding the fields to Quick Edit or Add New Term Metabox.
Lets start with displaying the textbox to accept classes. Since both pages display their data differently ( and pass separate parameters ) we have to create two separate functions and assign them to {$taxonomy}_add_form_fields
and {$taxonomy}_edit_form_fields
respectively. Both are commented to point out anything our of the ordinary.
/**
* Category "Add New" Page - Add Additional Field(s)
* @param string $taxonomy
*/
function category_fields_new( $taxonomy ) { // Function has one field to pass - Taxonomy ( Category in this case )
wp_nonce_field( 'category_meta_new', 'category_meta_new_nonce' ); // Create a Nonce so that we can verify the integrity of our data
?>
<div class="form-field">
<label for="category_fa">Font-Awesome Icon</label>
<input name="category_icon" id="category_fa" type="text" value="" style="width:100%" />
<p class="description">Enter a custom font-awesome icon - <a href="http://fontawesome.io/icons/" target="_blank">List of Icons</a></p>
</div>
<?php
}
add_action( 'category_add_form_fields', 'category_fields_new', 10 );
/**
* Category "Edit Term" Page - Add Additional Field(s)
* @param Object $term
* @param string $taxonomy
*/
function category_fields_edit( $term, $taxonomy ) { // Function has one field to pass - Term ( term object) and Taxonomy ( Category in this case )
wp_nonce_field( 'category_meta_edit', 'category_meta_edit_nonce' ); // Create a Nonce so that we can verify the integrity of our data
$category_icon = get_option( "{$taxonomy}_{$term->term_id}_icon" ); // Get the icon if one is set already
?>
<tr class="form-field">
<th scope="row" valign="top">
<label for="category_fa">Font-Awesome Icon</label>
</th>
<td>
<input name="category_icon" id="category_fa" type="text" value="<?php echo ( ! empty( $category_icon ) ) ? $category_icon : ''; ?>" style="width:100%;" /> <!-- IF `$category_icon` is not empty, display it. Otherwise display an empty string -->
<p class="description">Enter a custom Font-Awesome icon - <a href="http://fontawesome.io/icons/" target="_blank">List of Icons</a></p>
</td>
</tr>
<?php
}
add_action( 'category_edit_form_fields', 'category_fields_edit', 10, 2 );
The next step is to save our options. Since category creation and category edit will be handled the same way when saving, we’ll use the same function for both. We still need to use the created_{$taxonomy}
and edited_{$taxonomy}
. As mentioned toward the top, since Taxonomy Metadata does not exist we have to save our data to the options table which needs a unique name. This is why we give our option a unique name of {$taxonomy}_{$term_id}_icon
which, in this example, translates to category_1_icon
.
/**
* Save our Additional Taxonomy Fields
* @param int $term_id
*/
function save_category_fields( $term_id ) {
/** Verify we're either on the New Category page or Edit Category page using Nonces **/
/** Verify that a Taxonomy is set **/
if( isset( $_POST['taxonomy'] ) && isset( $_POST['category_icon'] ) &&
(
isset( $_POST['category_meta_new_nonce'] ) && wp_verify_nonce( $_POST['category_meta_new_nonce'], 'category_meta_new' ) || // Verify our New Term Nonce
isset( $_POST['category_meta_edit_nonce'] ) && wp_verify_nonce( $_POST['category_meta_edit_nonce'], 'category_meta_edit' ) // Verify our Edited Term Nonce
)
) {
$taxonomy = $_POST['taxonomy'];
$category_icon = get_option( "{$taxonomy}_{$term_id}_icon" ); // Grab our icon if one exists
if( ! empty( $_POST['category_icon'] ) ) { // IF the user has entered text, update our field.
update_option( "{$taxonomy}_{$term_id}_icon", htmlspecialchars( sanitize_text_field( $_POST['category_icon'] ) ) ); // Sanitize our data before adding to the database
} elseif( ! empty( $category_icon ) ) { // Category Icon IS empty but the option is set, they may not want an icon on this category
delete_option( "{$taxonomy}_{$term_id}_icon" ); // Delete our option
}
} // Nonce Conditional
} // End Function
add_action ( 'created_category', 'save_category_fields' );
add_action ( 'edited_category', 'save_category_fields' );
Finally, we need to clean up our options. Postmeta deletes itself when a post is deleted but Options do not. We need to manually delete these so that our options tables does not get bloated with orphaned options.
/**
* Essential Cleanup of our Options
* @param int $term_id
* @param string $taxonomy
*/
function remove_term_options( $term_id, $taxonomy ) {
delete_option( "{$taxonomy}_{$term_id}_icon" ); // Delete our option
}
add_action( 'pre_delete_term', 'remove_term_options', 10, 2 );
If we want to display each icon that has currently been assigned. Since we’re generating a Unique Option Name using the Taxonomy and Term ID we would get the options using that same formula. First let’s get our terms, then let’s loop through our terms.
$terms = get_terms( // Returns an array of Term Objects,
'category', // Pass our Taxonomy
array( // Pass our Arguments
'hide_empty' => false // Show ALL Terms
)
);
if( ! empty( $terms ) ) { // Make sure we have some terms to loop through
foreach( $terms as $term ) { // Loop through each term
$icon = get_option( "{$term->taxonomy}_{$term->term_id}_icon" ); // Use our formula to grab the Icon - This translate to "category_1_icon"
echo "Category {$term->name} Icon: {$icon}<br />"; // Display our Category Icon
}
}