WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I can't get the order of my posts (organized by custom tax terms) to come out right in my loop.

I made a custom post type of 'staff', in staff there is a custom taxonomy of 'staff-title'.

I added terms (similar to categories to keep the UI clean for the client) such as 'editor-in-chief', 'managing-editor', 'poetry-editor', etc. The idea is that the client can go into the 'staff' post type, create posts that are named after the employee and then check which position they hold and then the posts will be displayed in the proper order (displaying posts by running down the chain of command).

Here is the function creating my custom tax in functions.php:

function add_custom_taxonomies() {
    // Add new "Locations" taxonomy to Posts
    register_taxonomy('staff-title', 'staff', array(
        // Hierarchical taxonomy (like categories)
        'hierarchical' => true,
        // This array of options controls the labels displayed in the WordPress Admin UI
        'labels' => array(
            'name' => _x( 'Staff Titles', 'taxonomy general name' ),
            'singular_name' => _x( 'Title', 'taxonomy singular name' ),
            'search_items' =>  __( 'Search Titles' ),
            'all_items' => __( 'All Titles' ),
            'parent_item' => __( 'Parent Title' ),
            'parent_item_colon' => __( 'Parent Title:' ),
            'edit_item' => __( 'Edit Title' ),
            'update_item' => __( 'Update Title' ),
            'add_new_item' => __( 'Add New Title' ),
            'new_item_name' => __( 'New Title Name' ),
            'menu_name' => __( 'Staff Titles' ),
        // Control the slugs used for this taxonomy
        'rewrite' => array(
            'slug' => 'locations', // This controls the base slug that will display before each term
            'with_front' => false, // Don't display the category base before "/locations/"
            'hierarchical' => true // This will allow URL's like "/locations/boston/cambridge/"

add_action( 'init', 'add_custom_taxonomies', 0 );

Here is my WP_Query on the staff page...

$args = array(
    'post_type' => 'staff',
    'tax_query' => array(
               'taxonomy' => 'staff-title',
               'field' => 'slug',
               'terms' => array('editor-in-chief', 'managing-editor', 'fiction-editor', 'poetry-editor', 'nonfiction-editor', 'production-manager' )
        'posts_per_page' => '-1',
        'order' => 'ASC',
        'orderby' => 'meta_value_num'

$my_query = new WP_Query( $args );

The tax_query 'terms' => array(...) has the terms (staff positions) listed in the order they should be displaying but this isn't the case.

Visiting the staff page the posts are displaying in this order, which is the WRONG order:

Editor in Chief - Ching-in Chen
Managing Editor - Shanae Martinez
Production Manager - Matthew Morris-Cook
Nonfiction Editor - Kate Nesheim
Poetry Editor - C. McCallister Williams
Poetry Editor - Kara van de Graaf
Fiction Editor - Loretta McCormick
Fiction Editor - Mollie Boutell

Here's the CORRECT order just for reference (same order as the tax query terms array):

Editor in Chief - Ching-in Chen
Managing Editor - Shanae Martinez
Fiction Editor - Loretta McCormick
Fiction Editor - Mollie Boutell
Poetry Editor - C. McCallister Williams
Poetry Editor - Kara van de Graaf
Nonfiction Editor - Kate Nesheim
Production Manager - Matthew Morris-Cook

I put up the staff names as they are the title of the individual posts and I thought they might be a part of the problem.

Anyone have any ideas on how I could fix this? If you need more information let me know I'd be happy to provide. Thanks in advance!

share|improve this question
If someone stumbles upon this, take a look at make.wordpress.org/core/2014/08/29/… for more improved order-functionality – bestprogrammerintheworld Oct 7 '15 at 22:14

It's already a hierarchical post type - no need for some extra meta value just for the order. You can simply add post type support for page-attributes when registering the post type. This will give you the "menu order" meta box that pages have per default.

Then simply order your query by it:

'orderby' => 'menu_order'
share|improve this answer

You can't oder by taxonomy term with WP_Query. You could do it with some custom SQL, but if the terms are hardcoded into the query anyway, just iterate over an array of terms in the order you want, then for each term loop over the posts within and check if it's associated to that term-

$args = array(
    'post_type' => 'staff',
    'posts_per_page' => '-1'
$my_query = new WP_Query( $args );
$terms = array(
foreach( $terms as $term ){
    while( $my_query->have_posts() ){
        if( has_term( $term ) ){
            // output post
share|improve this answer
Oh I didn't realize that tax terms can't be ordered like this. Is there a better way for me to go about this completely than how I am? or would you suggest sticking with your answer? Also I think at some point the client wants to be able to add new terms (if new staff positions are created), it'd be nice if they could introduce themselves into the code automatically or with little trouble. – user47713 Feb 17 '14 at 18:21

Another workaround is a custom post meta field, with a select of all available taxonomy terms staff-title. On the save action of your post you can even add the handling of your post term relationship.

function my_staff_title_term_meta_box($post) {
    $staff_title= get_post_meta($post->ID, '_staff_title_term_slug', true);
    $terms = get_terms('staff-title', array('hide_empty' => false));
    // your term slugs are the ones manipulating the order, e.g. title-1 for the first title to appear and so on…
    echo "<select name='staff_title_term_slug' id='staff_title_term_slug'>";
    echo "<option value=''".(empty($staff_title)?" selected='selected'":'').">".__('No staff title', 'my_textdomain')."</option>";
    if (!empty($terms) && is_array($terms)) foreach ($terms as $term) {
        echo "<option value='{$term->slug}'".(!empty($staff_title) && $staff_title == $term->slug?" selected='selected'":'').">{$term->name}</option>";
    echo "</select>";

function add_my_staff_title_term_meta_box() {
        __('Staff Title','my_textdomain'),

add_action( 'add_meta_boxes', 'add_my_staff_title_term_meta_box');

function save_my_stuff_title_term($post_id) {
    if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
    if ( !current_user_can( 'edit_post', $post_id ) )
    if ($_POST['staff_title_term_slug']) {
        update_post_meta($post_id, '_staff_title_term_slug', $_POST['staff_title_term_slug']);
    } else {
        delete_post_meta($post_id, '_staff_title_term_slug');
    //TODO: Additionally handling ticked staff title terms, e.g. overwrite them with chosen slug

add_action( 'save_post', 'save_my_stuff_title_term' );

In your front-end query you can order by your post-meta field.

function filter_my_staff_query( $query ) {
    if ( $query->is_main_query() && $query->is_archive() && $query->get('post_type') === 'staff'  && !is_admin()) {
        $query->set('meta_key', '_staff_title_term_slug');
        $query->set('orderby', 'meta_value');

add_action( 'pre_get_posts', 'filter_my_staff_query' );
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.