Ordering terms before displaying posts

My question is close to other questions, but I dont’ have enough reputation to comment.

I’m working for a restaurant and I ‘d like, for my menu page, to organise my posts “meal” under terms “cat_meal”.

This terms should respect an order (dessert after starter for example). And that’s my probleme : I tried so many snippets, that I don’t know which one I should write here…
Here are some picture to explain, I hope.
Page menu
Page menu with comments
But, there is always something wrong : either I can display my term in a right order and my query post is not good. Or meal posts are under the good terms, but, the order of the terms are wrong. Or, worth, nothing happens.

Here are two tests, thanks for your time and help :

$args_tax = [
    'parent'    => 0,
    'hide_empty' => 0,
    'meta_key'      => 'ordre',// I added an ACF with number from 1 to 8 to order
    'orderby'   => 'meta_value',
    'order'     => 'ASC'
];

$terms = get_terms('cat_meal', $args_tax); // tax cat_meal
// print_r($terms);

if (!empty($terms)):
    foreach ($terms as $term):
        $argsPost = [
            'post_type' => 'meal',//CPT meal
             'posts_per_page' => -1
        ];

        $query = new WP_Query($argsPost);
        while ($query->have_posts()) : $query->the_post();
            echo $term->name ;
            the_title();
        endwhile;
        wp_reset_postdata(); // reset the query 
    endforeach;
endif;
//PROBLEM : under each term, every posts are displaying ! I don't understand why...

Second version from this question Get all categories and posts in those categories


$args = array( 
        'post_type' => 'meal',  
        'posts_per_page' => -1
    );

    $query = new WP_Query($args);   
    $q = array();

    while ( $query->have_posts() ) { 
        $query->the_post(); 
        $a="" . get_the_title() .'';
        $terms = wp_get_post_terms( $post->ID, 'cat_meal', $args );
        foreach ( $terms as $term) {
            $term_link = get_term_link( $term );
            $b = ''.$term->name.'';    
        }
        $q[$b][] = $a; 
    }
    wp_reset_postdata();
    foreach ($q as $key=>$values) {
        echo $key;
            foreach ($values as $value){
                echo $value;
            }
    }

The posts are well displaying under the terms, BUT the terms have wrong order (dessert before pizza)

I’ve just found this answer too, but I’ dont undetsand wher the taxonomy is declared : Ordering Posts with Custom Taxonomy Terms Array.

I would really appreciate some advices into my fog : thanks

2 Answers
2

You could use tax_query to get only the posts with the term that is currently being looped.

$argsPost = [
 'post_type' => 'meal',//CPT meal
 'posts_per_page' => -1,
 'meta_key' => 'ordre', 
 'orderby'   => 'meta_value', // Use the custom post order
 'order'     => 'ASC' 
 'tax_query' => array(
    array(
        'taxonomy' => 'cat_meal',
        'field'    => 'term_id',
        'terms'    => $term->term_id, // Only query the posts that have the current term in foreach loop
    ),
 ),
];

Try replacing the $argsPost in your first code example with this one and see what happens.

I have a vague memory of doing something like this myself on couple of sites.

EDIT 20.10.2018

I looked at the Ordering Posts with Custom Taxonomy Terms Array discussion that you had linked and you could also use the solution Milo had posted.

Something like this (might need some tweaking)

$args = array(
'post_type' => 'meal',
'posts_per_page' => '-1',
// add extra sorting related key/value pairs here
);
$my_query = new WP_Query( $args );

// you original get_terms function
$args_tax = [
'parent'    => 0,
'hide_empty' => 0,
'meta_key'      => 'ordre',// I added an ACF with number from 1 to 8 to order
'orderby'   => 'meta_value',
'order'     => 'ASC'
];
$terms = get_terms('cat_meal', $args_tax); // tax cat_meal

// Loop terms
if ( ! is_wp_error( $terms ) && ! empty( $terms )  ) {
    foreach( $terms as $term ) {
        while( $my_query->have_posts() ) {
            $my_query->the_post();
            if( has_term( $term->term_id, 'cat_meal' ) ){
                // output post
            }
        }
        $my_query->rewind_posts(); // rewind custom query for the next foreach term loop
    }
}

This way you would only make one WP_Query and just loop the results over and over again for each term. This might be better performance wise instead of doing separate WP_Query for each term, but this is just a hunch.

Leave a Comment