Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a site with about 1,000 posts spread out over 70 or 80 categories. Some of these categories require the posts be sorted by a custom field, others not.

I've got a working solution by having 60+ category template files defined (e.g. category-123.php, category-124.php) and each of those calls a separate loop file:

get_template_part( 'loop-123', 'category' );

The loop-123 file then runs a new query and sorts it correctly before passing it to the loop:

<?php
$the_query = new WP_Query("cat=123&meta_key=programnumber&orderby=meta_value&order=ASC");
?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>

However, there has to be a more efficient way to do this than to create 60+ file pairs. I'm just not seeing it, though.

share|improve this question

2 Answers 2

up vote 2 down vote accepted

I would suggest to hook onto pre_get_posts and alter the query, rather than firing off your own in the template (it keeps your template tidy, and you'll avoid doubling your database queries!).

Below demonstrates this, plus a bonus settings field in the admin (under "Reading") to select the categories that "special sorting" applies to - see how easy the settings API really is!

/**
 * Intercept the query & attach our own parameters if the conditions are met.
 */
function wpse_42457_custom_category_order( $wp_query )
{
    if ( ! $wp_query->is_category() ) // save proceeding processing
        return;

    $special_categories = wp_parse_id_list( get_option( 'sorted_categories' ) );
    if ( $wp_query->is_category( $special_categories ) ) {

        // We've got a winner - set our special params.
        $wp_query->set( 'meta_key', 'programnumber' );
        $wp_query->set( 'orderby', 'meta_value' );
        $wp_query->set( 'order', 'ASC' );
    }
}
add_action( 'pre_get_posts', 'wpse_42457_custom_category_order' );

/**
 * Register the sorted categories option & the settings field.
 */
function wpse_42457_admin_init()
{
    add_settings_field( 'sorted_categories', 'Special Categories', 'wpse_42457_setting_field', 'reading', 'default' );
    register_setting( 'reading', 'sorted_categories', 'wpse_42457_setting_sanitize' );
}
add_action( 'admin_init', 'wpse_42457_admin_init' );

/**
 * Sanitize our checked categories by turning back to a comma-delimited string.
 *
 * This'll save bytes in the options table, plus it can be "unserialized" more
 * efficiently with wp_parse_id_list() when it's actually needed.
 */
function wpse_42457_setting_sanitize()
{
    // wp_terms_checklist uses "post_category" POST name.
    if ( isset( $_POST['post_category'] ) )
        $value = $_POST['post_category'];
    else
        $value = array(); // none checked

    return implode( ',', wp_parse_id_list( $value ) );
}

/**
 * Display the sorted categories field.
 */
function wpse_42457_setting_field()
{
    // Please forgive me for this dirty HTML!
    ?>

<style>#sorted_categories li li { margin: 0 0 0 15px }</style>
<ul id="sorted_categories">
    <?php
        wp_terms_checklist( 0, array(
            'selected_cats' => wp_parse_id_list( get_option( 'sorted_categories' ) ),
            'checked_ontop' => false,
            'taxonomy' => 'category'
        ));
    ?>
</ul>

    <?php
}

Whilst I always feel like I should encourage others to take steps for themselves, this proved easier to code up than walk through - hopefully it'll be educational nontheless!


You'll need to drop this in a custom plugin, or your theme's functions.php.

share|improve this answer
    
Whoa. Wasn't expecting THAT! Thanks @TheDeadMedic, that's some good stuff. –  JCL1178 Feb 15 '12 at 22:07

How about this, create an option in the options table (in the database) with an array of categories ids that need a custom sorting ex:

<?php
$cats_to_sort = array(21,33,43,66); //add as many as you need.
update_option('cats_to_sort',$cats_to_sort);
?>

then creat a single category.php file with a simple loop but before the loop check if this category needs to be sorted by a custom field ex:

<?php
//get the saved array
$cats_to_sort = get_option('cats_to_sort');
//get the category id, this works for custom taxonomies as well.
$term_slug = get_query_var( 'term' );
$taxonomyName = get_query_var( 'taxonomy' );
$term = get_term_by( 'slug', $term_slug, $taxonomyName );
if (in_array($term->term_id,$cats_to_sort)){
    query_posts("cat=".$term->term_id."&meta_key=programnumber&orderby=meta_value&order=ASC");
}
//you loop here
?>
share|improve this answer
    
I can see what you are going for but I couldn't seem to get it to work. –  JCL1178 Feb 15 '12 at 22:07

Your Answer

 
discard

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.