Order get_terms() By Custom Field

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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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 );

Method 2

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;
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x