Site icon WP Smith

How to orderby include Argument for get_terms()

WordPress 3.5 came out with an awesome feature of ordering by post__in (Codex). So when I got to my current issue, I noticed that I could not use the default orderby options (alphabetical title, ID, etc.), so the code used to create the post__in orderby can also be extended to be used for get_terms, which by default is not available in WordPress core. However, there is a great filter to enable this (see WordPress ticket).

Call get_terms()

So, first, I need to setup the function. In this scenario, I am using WooCommerce, but it could work with any theme, or ecommerce solution. For more information on get_terms() please see the WordPress Codex.

<?php
/**
* Output the homepage categories HTML Markup
*
* @uses wps_category_image() Outputs image HTML Markup
*/
function wps_homepage_categories() {
$args = array(
'orderby' => 'include',
'order' => 'ASC',
'hide_empty' => false,
'include' => array( 28 /* Appearal */, 27 /* Accessories */, 30 /* Outerwear */, 29 /* Hiking */, 22 /* Grooming */, ),
'fields' => 'all',
'pad_counts' => false,
'd2c_home' => true, //optional
);
$product_cats = get_terms( 'product_cat', $args );
foreach ( $product_cats as $cat ) {
wps_category_image( $cat->term_id, $size );
}
}

In this code, I use wps_category_image() which outputs the WooCommerce category image.

<?php
/**
* Outputs HTML markup for category image for WooCommerce.
*
* @param int $cat_id Category ID.
* @param string $size Image size.
* @param array $attr Image attributes.
* @return string $orderby Modified orderby SQL string.
*/
function wps_category_image( $cat_id, $size, $attr = array() ) {
// get the thumbnail id user the term_id
$thumbnail_id = get_woocommerce_term_meta( $cat_id, 'thumbnail_id', true );
// get the image URL
$image = wp_get_attachment_url( $thumbnail_id );
// print the IMG HTML
echo wp_get_attachment_image( $thumbnail_id, $size, false, $attr );
}

Filter get_terms_orderby

Next, is the really cool part. You want to filter the get_terms_orderby SQL.

<?php
add_filter( 'get_terms_orderby', 'wps_get_terms_orderby', 10, 2 );
/**
* Modifies the get_terms_orderby argument if orderby == include
*
* @param string $orderby Default orderby SQL string.
* @param array $args get_terms( $taxonomy, $args ) arg.
* @return string $orderby Modified orderby SQL string.
*/
function wps_get_terms_orderby( $orderby, $args ) {
if ( isset( $args['orderby'] ) && 'include' == $args['orderby'] ) {
$include = implode(',', array_map( 'absint', $args['include'] ));
$orderby = "FIELD( t.term_id, $include )";
}
return $orderby;
}

First, you need to check to see if include is the preferred orderby argument.

Second, you want to sanitize it with absint().

Third, set the order to the FIELD include (see here for more information).