I’m trying to figure out how to arrange tags on a post using a method other than alphabetically. For example, a post has the following tags; alpha
, beta
, charlie
. The post will always organize tags in that order.
I’d like to control the way tags are displayed on a post. Instead of alphabetically, I’d like to order post tags by the order they were added to the post. For example; alpha
(entered2nd), beta
(entered1st), charlie
(entered3rd) would be added to a post, but the tags would be listed in this order naturally, alpha, beta, charlie
. I’d like them to be displayed in this order; beta, alpha, charlie
Is this possible? If yes, can you please direct me?
One way to do it is to store the order of the tags as post meta data, using the action set_object_terms
which happens to pass the tags in the order they appear on edit, eg in your “functions.php”:
// Called in admin on updating terms - update our order meta.
add_action( 'set_object_terms', function ( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
if ( $taxonomy != 'post_tag' ) {
return;
}
// Save in comma-separated string format - may be useful for MySQL sorting via FIND_IN_SET().
update_post_meta( $object_id, '_tt_ids_order', implode( ',', $tt_ids ) );
}, 10, 6 );
// Reorder terms using our order meta.
function wpse174453_get_the_terms( $terms, $post_id, $taxonomy ) {
if ( $taxonomy != 'post_tag' || ! $terms ) {
return $terms;
}
if ( $ids = get_post_meta( $post_id, '_tt_ids_order', true ) ) {
$ret = $term_idxs = array();
// Map term_ids to term_taxonomy_ids.
foreach ( $terms as $term_id => $term ) {
$term_idxs[$term->term_taxonomy_id] = $term_id;
}
// Order by term_taxonomy_ids order meta data.
foreach ( explode( ',', $ids ) as $id ) {
if ( isset( $term_idxs[$id] ) ) {
$ret[] = $terms[$term_idxs[$id]];
unset($term_idxs[$id]);
}
}
// In case our meta data is lacking.
foreach ( $term_idxs as $term_id ) {
$ret[] = $terms[$term_id];
}
return $ret;
}
return $terms;
}
// Called in front-end via the_tags() or related variations of.
add_filter( 'get_the_terms', 'wpse174453_get_the_terms', 10, 3 );
// Called on admin edit.
add_filter( 'terms_to_edit', function ( $terms_to_edit, $taxonomy ) {
global $post;
if ( ! isset( $post->ID ) || $taxonomy != 'post_tag' || ! $terms_to_edit ) {
return $terms_to_edit;
}
// Ignore passed in term names and use cache just added by terms_to_edit().
if ( $terms = get_object_term_cache( $post->ID, $taxonomy ) ) {
$terms = wpse174453_get_the_terms( $terms, $post->ID, $taxonomy );
$term_names = array();
foreach ( $terms as $term ) {
$term_names[] = $term->name;
}
$terms_to_edit = esc_attr( join( ',', $term_names ) );
}
return $terms_to_edit;
}, 10, 2 );