I am trying to sort my taxonomy terms table by a custom field in Wordpress. But I am missing something.
I have a custom taxonomy. Let’s call it education in this example.
I added a field sort-order and save a value to that field using update_term_meta()
.
This works.
Next I added a column to the admin table for the taxonomy:
// Add the column to the table with terms
add_filter('manage_edit-education_columns', array( $this, 'addSortOrderColumn' ));
function addSortOrderColumn( $columns ){
$columnsBefore = array_slice( $columns, 0, 2, true); // NOTE: First column is the checkbox
$columnsAfter = array_slice( $columns, 2, count( $columns ), true);
$columnsInsert = array('sort-order' => ‘Sort’ );
$columns = array_merge($columnsBefore, $columnsInsert, $columnsAfter);
return $columns;
}
// Display the contents for the column
add_filter('manage_education_custom_column',array( $this, 'addSortOrderColumnContent'), 10, 3 );
function addSortOrderColumnContent( $content, $columnName, $termId ){
if( $columnName !== 'sort-order' ){
return $content;
}
$termId = absint( $termId );
$order = get_term_meta( $termId, 'sort-order', true );
if( !empty( $order ) ){
$content .= esc_attr( $order );
}
return $content;
}
// Make the column sortable
add_filter( 'manage_edit-education_sortable_columns', array( $this, 'makeSortOrderColumnSortable' ));
function makeSortOrderColumnSortable( $sortable ){
$sortable[ 'sort-order' ] = 'sort-order';
return $sortable;
}
I see the column, I can click its header and it flips the table rows on click ( a c z e <-> e z c a ), but it does not sort it based on the contents.
What do I need to add to make the sorting aware of the column contents?
You need to tweak the underlying sql that the get_terms function runs to retrieve the taxonomy terms list. It defaults to the term name, clicking & changing the sort will change the orderby=xxx in the url, but will flow through the switch statement in the code and return to the default. The way to do it is through the terms_clauses filter:
add_filter( 'terms_clauses', 'filter_terms_clauses', 10, 3 );
/**
* Filter WP_Term_Query meta query
*
* @param object $query WP_Term_Query
* @return object
*/
function filter_terms_clauses( $pieces, $taxonomies, $args ) {
global $pagenow, $wpdb;
// Require ordering
$orderby = ( isset( $_GET['orderby'] ) ) ? trim( sanitize_text_field( $_GET['orderby'] ) ) : '';
if ( empty( $orderby ) ) { return $pieces; }
// set taxonomy
$taxonomy = $taxonomies[0];
// only if current taxonomy or edit page in admin
if ( !is_admin() || $pagenow !== 'edit-tags.php' || !in_array( $taxonomy, [ 'education' ] ) ) { return $pieces; }
// and ordering matches
if ( $orderby === 'sort-order' ) {
$pieces['join'] .= ' INNER JOIN ' . $wpdb->termmeta . ' AS tm ON t.term_id = tm.term_id ';
$pieces['where'] .= ' AND tm.meta_key = "sort-order"';
$pieces['orderby'] = ' ORDER BY tm.meta_value ';
}
return $pieces;
}
The WP_Term_Query is only from WP4.6 so this functionality is pretty fresh.