6

I want to order my categories like I order my pages. I've added an extra field called Order to my taxonomy, but how do I order my terms by this value?

Adding and Saving my Order Value:

/** Add New Field To Category **/
function extra_category_fields( $tag ) {
    $t_id = $tag->term_id;
    $cat_meta = get_option( "category_$t_id" );
?>
<tr class="form-field">
    <th scope="row" valign="top"><label for="meta-order"><?php _e('Category Order'); ?></label></th>
    <td>
        <div id="catOrder">
            <input type="text" name="cat_meta[order]" size="3" style="width:5%;" value="<?php echo (isset($cat_meta['order'])) ? $cat_meta['order'] : '0'; ?>" />
        </div>
        <span class="description"><?php _e('Categories are ordered Smallest to Largest'); ?></span>
    </td> 
</tr>
<?php
}
add_action('protax_edit_form_fields','extra_category_fields');  

/** Save Category Meta **/
function save_extra_category_fileds( $term_id ) {
    if ( isset( $_POST['cat_meta'] ) ) {
        $t_id = $term_id;
        $cat_meta = get_option( "category_$t_id");
        $cat_keys = array_keys($_POST['cat_meta']);
            foreach ($cat_keys as $key){
            if (isset($_POST['cat_meta'][$key])){
                $cat_meta[$key] = $_POST['cat_meta'][$key];
            }
        }
        //save the option array
        update_option( "category_$t_id", strip_tags($cat_meta) );
    }
}
add_action ( 'edited_protax', 'save_extra_category_fileds');

Normally I could retrieve this value such as:

$categories = get_categories(array('taxonomy' => 'protax'));
foreach($categories as $cat){
    $tmp = get_option('category_'.$cat->cat_ID);
    echo $tmp['order'];
}

Is it possible to order by this custom value? Is there a better way to manually order my categories?

9
  • 1
    get_categories as an option to order by term_group. Term group is a field in wp_terms table that AFAIK is not used by WordPress. So you can use the extra field to set the term_group and then use 'orderby' => 'term_group' in $args array for get_categories.
    – gmazzap
    Commented Oct 8, 2013 at 16:45
  • :/ I'm not sure I follow. When or where do I set term_group?
    – Howdy_McGee
    Commented Oct 8, 2013 at 17:00
  • 1
    $wpdb->update($wpdb->terms, array('term_group' => $cat_meta['order']), array('term_id'=>$term_id)); you need a WHERE clause and $cat_meta['order'] not all the $cat_meta array
    – gmazzap
    Commented Oct 8, 2013 at 17:18
  • 1
    In codex for get_categories orderby term_group is cited with any advice, but in codex for get_terms is said "not fully implemented (avoid using)" so isn't only your problem... sorry for your time loose, I remember I've used it with no problems...
    – gmazzap
    Commented Oct 8, 2013 at 18:12
  • 1
    No no, thank you for your help! I got it to work with get_categories - I was misspelling orderby: Solution is in my Question - again thank you for your help!!!
    – Howdy_McGee
    Commented Oct 8, 2013 at 18:30

2 Answers 2

8

SOLUTION - Updated: 03/03/2015 - Thanks to /u/G.M.

The below adds a new field to the Term Edit Page and saves the value into the un-used ( for the moment anyway ) term_group field which can then be used to order terms. In the below hooks ( actions ) you'll need to replace TAXONOMY_SLUG with your actual taxonomy slug.

/**
 * Append Fields To Term Edit Page
 * @param Term Object $term
 * @param string $taxonomy
 */
function term_order_field( $term, $taxonomy ) {
  ?>
    <tr class="form-field">
        <th scope="row" valign="top">
            <label for="meta-order"><?php _e( 'Category Order' ); ?></label>
        </th>
        <td>
            <input type="text" name="_term_order" size="3" style="width:5%;" value="<?php echo ( ! empty( $term->term_group ) ) ? $term->term_group : '0'; ?>" />
            <span class="description"><?php _e( 'Categories are ordered Smallest to Largest' ); ?></span>
        </td> 
    </tr>
  <?php
}
add_action( 'TAXONOMY_SLUG_edit_form_fields', 'term_order_field', 10, 2 );

/**
 * Save Term Order
 * @param int $term_id
 */
function save_term_order( $term_id ) {
    global $wpdb;

    if( isset( $_POST['_term_order'] ) ) {
        $wpdb->update( 
            $wpdb->terms,
            array(
                'term_group' => $_POST['_term_order']
            ),
            array( 
                'term_id'    => $term_id
            )
        );
    }
} // END Function
add_action( 'edited_TAXONOMY_SLUG', 'save_term_order' );

Add Term Order cell to Term List

/**
 * Add Column To Show 'Term Order' Field
 * @param array $columns
 * @return array $columns
 */
function term_order_header( $columns ) {
    $columns['order'] = '<center>Order</center>';
    return $columns;
}
add_filter( 'manage_edit-TAXONOMY_SLUG_columns', 'term_order_header' );

/**
 * Give 'Term Order' Column A Value `term_group`
 * @param string $empty
 * @param string $col_name
 * @param int $term_id
 * @return string
 */
function term_order_header_val( $empty = '', $col_name, $term_id ) {
    if( isset( $_GET['taxonomy'] ) && 'order' == $col_name ) {
        $term = get_term( $term_id, $_GET['taxonomy'] );
        return "<center>{$term->term_group}</center>";
    } else {
        return '0';
    }
}
add_filter( 'manage_TAXONOMY_SLUG_custom_column', 'term_order_header_val', 10, 3 );

Hook Documentation


Below is an out-dated solution that works better if you have multiple Term Meta Values you would like to save. If you only need to save Term Order, the above solution is best.

/** Add New Field To Category **/
function extra_category_fields( $tag ) {
    $t_id = $tag->term_id;
    $cat_meta = get_option( "category_$t_id" );
?>
<tr class="form-field">
    <th scope="row" valign="top"><label for="meta-order"><?php _e('Category Order'); ?></label></th>
    <td>
        <div id="catOrder">
            <input type="text" name="cat_meta[order]" size="3" style="width:5%;" value="<?php echo (isset($cat_meta['order'])) ? $cat_meta['order'] : '0'; ?>" />
        </div>
        <span class="description"><?php _e('Categories are ordered Smallest to Largest'); ?></span>
    </td> 
</tr>
<?php
}
add_action('protax_edit_form_fields','extra_category_fields');  

/** Save Category Meta **/
function save_extra_category_fileds( $term_id ) {
    global $wpdb;
    if ( isset( $_POST['cat_meta'] ) ) {
        $t_id = $term_id;
        $cat_meta = get_option( "category_$t_id");
        $cat_keys = array_keys($_POST['cat_meta']);
            foreach ($cat_keys as $key){
            if (isset($_POST['cat_meta'][$key])){
                $cat_meta[$key] = $_POST['cat_meta'][$key];
            }
        }
        update_option( "category_$t_id", $cat_meta );
        $wpdb->update($wpdb->terms, array('term_group' => $cat_meta['order']), array('term_id'=>$term_id));
    }
}
add_action ( 'edited_protax', 'save_extra_category_fileds');

Calling it:

$procats = get_categories(array('taxonomy' => 'protax', 'hide_empty' => 0, 'orderby' => 'term_group'));

Edit - You're also able to order them in the admin panel by using this filter:

function change_term_order( $orderby, $args, $taxonomies ) {
    if ( is_admin() && 'protax' !== $taxonomies[0] )
        return $orderby;

    $orderby = 'term_group';
    $args['order'] = 'ASC';
    return $orderby;
}
add_filter( 'get_terms_orderby', 'change_term_order', 10, 3 );
2
  • So I remember well :) +1 to reward your tenacity and my suggestion...
    – gmazzap
    Commented Oct 8, 2013 at 19:10
  • Thanks for this. It convinced me to create a custom post type and link posts to taxonomy terms that hold the custom fields, as opposed to adding custom fields to the taxonomy itself. Without being able to use the loop for taxonomy terms the same way it works for posts, this would have been a real headache.
    – cdonner
    Commented Jun 12, 2014 at 15:51
0

What about this:

$terms_hearing = merge_tax_and_custom_field(
    get_terms([
        'taxonomy'   => 'hearing',
        'hide_empty' => false,
    ]),
    'abbr'
);

sort_tax_by_custom_field($terms_hearing, 'abbr');

// function will allow to merge taxonomy result with custom taxonomy terms
function merge_tax_and_custom_field($terms, $field)
{
    // merge custom field into original taxonomy object
    foreach ($terms as $index => $term) {
        // grabbing custom field data
        $data = get_option('taxonomy_term_' . $term->term_id)[$field];

        // adding data field into term object as property
        $terms[$index]->{$field} = $data;
    }

    return $terms;
}

// sort field by custom field value
function sort_tax_by_custom_field($terms, $field)
{
    usort($terms, function ($a, $b) {
        return strcmp($a->abbr, $b->abbr);
    });

    return $terms;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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