How to sort get_terms() results in a specific order

I am populating an unordered list by the results from get_terms() assigned to a variable. What I would like to do is order the results in a specific order in the unordered list. How would I do this? I looked into using the orderby argument for the get_terms() function but none of the parameters for that seem to work the way I need them to. How do I define a specific order for them to be displayed in? So basically my unordered list looks like this once populated:

  • Atletics
  • Community
  • Corporate
  • Healthcare
  • Higher Education
  • k-12

And I want it to look like this:

  • k-12
  • higher education
  • healthcare
  • atletics
  • Corporate
  • community

Related posts

2 comments

  1. The best option is to write a wrapper function for get_terms and then use usort() to sort the terms in the order you want.

    Here is the code, I have commented the code to make it easy to follow and to understand (NOTE: This code requires PHP 5.4+)

    function get_terms_ordered( $taxonomy = '', $args = [], $term_order = '', $sort_by = 'slug' )
    {
        // Check if we have a taxonomy set and if the taxonomy is valid. Return false on failure
        if ( !$taxonomy )
            return false;
    
        if ( !taxonomy_exists( $taxonomy ) )
            return false;
    
        // Get our terms    
        $terms = get_terms( $taxonomy, $args ); 
    
        // Check if we have terms to display. If not, return false
        if ( empty( $terms ) || is_wp_error( $terms ) )
            return false;
    
        /** 
         * We have made it to here, lets continue to output our terms
         * Lets first check if we have a custom sort order. If not, return our
         * object of terms as is
         */
        if ( !$term_order )
            return $terms;
    
        // Check if $term_order is an array, if not, convert the string to an array
        if ( !is_array( $term_order ) ) {
            // Remove white spaces before and after the comma and convert string to an array
            $no_whitespaces = preg_replace( '/s*,s*/', ',', filter_var( $term_order, FILTER_SANITIZE_STRING ) );
            $term_order = explode( ',', $no_whitespaces );
        }
    
        // Remove the set of terms from the $terms array so we can move them to the front in our custom order
     $array_a = [];
     $array_b = [];
        foreach ( $terms as $term ) {
            if ( in_array( $term->$sort_by, $term_order ) ) {
                $array_a[] = $term;
            } else {
                $array_b[] = $term;
            }
        }
    
        /**
         * If we have a custom term order, lets sort our array of terms
         * $term_order can be a comma separated string of slugs or names or an array
         */
        usort( $array_a, function ( $a, $b ) use( $term_order, $sort_by )
        {
            // Flip the array
            $term_order = array_flip( $term_order );
    
            return $term_order[$a->$sort_by] - $term_order[$b->$sort_by];
        });
    
        return array_merge( $array_a, $array_b );
    }   
    

    There are four parameters to the function

    • $taxonomy This is the taxonomy from which to get terms from. Default: empty string

    • $args This is all the valid arguments that can be passed to get_terms. You can check out get_terms for valid arguments. Default: empty array

    • $term_order The slugs or names or ids of the terms in the specific order you want them sorted. This can be an array of slugs/names/ids or a comma separated string of slugs/names/ids. Default empty string

      Examples

      string: $term_order = 'term-3, term-1, term-2';
      array:  $term_order = ['term-3', 'term-1', 'term-2'];
      

      This will display the terms in order of term-3, term-1, term-2

    • $sort_by By which field the terms must be sorted. The default value is slugs, so this means that you should pass a string or an array of terms slugs to the $term_order parameter. If you need to pass term names to the $term_order parameter, then you need to set the value of $sort_by to name. You can also pass, if you wish, term ids to $term_order, in which case you then need to set the $sort_by value to term_id

    USAGE

    In your template, you will use the function as follow with the following example

    Taxonomy name is category, we don’t want to set any specific argument, we need sort the terms by name in the following order Term C, Term A, Term B

    You will then do the following: ($term_order as an array)

    $terms = get_terms_ordered( 'category', [], ['Term C', 'Term A', 'Term B'], 'name');
    var_dump( $terms);
    

    ($term_order as a string)

    $terms = get_terms_ordered( 'category', [], 'Term C, Term A, Term B', 'name');
    var_dump( $terms);
    
  2. One problem I’ve found with setting an order that the client wants, is that the client will later want to re-order the list so another way to allow a desired order and ability to alter that later without adjusting the code would be the following:

    1. Create a custom field for the taxonomy terms. A great way is using Advanced Custom Fields plugin which makes this field editable in the dashboard.
    2. Give that custom field a default value of ‘0’.
    3. Use the get_terms() function and include the following settings in the array. In this example jht_order is the name of the custom field.
    'orderby'  => 'meta_value',
    'meta_key' => 'jht_order',
    

    Now the terms will be ordered by the value of this field. Note: if the term doesn’t have this field populated, it won’t be returned by get_terms()

    Update: If the custom field is a number, you’ll want to change ‘orderby’ to be ‘meta_value_num’ so it will sort it as a number and not as ascii.

    'orderby'  =>  'meta_value_num'
    

Comments are closed.