Wordpress order posts by post type

2019-01-26 01:18发布

问题:

I am trying to create a system which fetches post from 2 post types and i want to display the posts order by their post type. I am trying to first show the posts from one post type and then another post type but the query i used mixes it all. Can any one suggest a good solution for this. Here is my code.

    $paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
 $args = array(

     'post_type' => array('review','directory'),
     'orderby' => 'name',
     'order' => 'ASC',
     'posts_per_page'  => '4',
     'paged'          => $paged ,
     'tax_query' => array( array(
        'taxonomy' => 'Reviews',
        'field' => 'id',
        'terms' => $cat_id
    ), ),
     );

 query_posts($args);
        if (have_posts()) :
       while (have_posts()) : the_post();
      $product_terms = wp_get_post_terms(get_the_ID(), 'Reviews', array("fields" => "all", "order" => "DESC"));
      $postype=get_post_type( get_the_ID() );
      if($postype=='review')
      {
     ?>   

        <div class="review-post">
          <a href="http://<?php the_permalink(); ?>" target="_blank"><h3><?php the_title(); ?></h3></a>
          <div class="review-cat-new">
            <?php echo get_the_term_list( $post->ID, 'Reviews', 'Category: ', ', ', '' ); ?>
          </div>

          <?php
          if(get_field('see_it'))
              $seeit_text= get_field('see_it');
         if(get_field('skip_it'))
              $skipit_text= get_field('skip_it');
         ?>
          <div class="see-skip">
            <p class="see-it"><span>See it:</span>
                <?php echo $seeit_text; ?>
            </p>
            <p class="skip-it"><span>Skip it:</span>
                <?php echo $skipit_text;  ?>
            </p>
          </div>
          <?php echo custom_field_excerpt(); ?>
        </div>
          <?php }
          else
          {
              ?>
                <div class="review-post">
          <a href="h<?php the_permalink(); ?>" target="_blank"><h3><?php the_title(); ?></h3></a>
          <div class="review-cat-new">
            <?php echo get_the_term_list( get_the_ID(), 'Reviews', 'Category: ', ', ', '' ); ?>
          </div>


          <?php echo the_field('enter_content_direc'); ?>
          <?php
          if(get_field('enter_textdirec'))
              $text= get_field('enter_textdirec');
         if(get_field('enter_linkdirec'))
              $textlink= get_field('enter_linkdirec');
         ?>
          <div class="see-skip">
            <p class="see-it direc"><span><a  target="_blank" style="color:#5D6D71; text-transform: lowercase;" href="<?php echo $textlink;?>"><?php echo $textlink;?>  </a></span>

            </p>
          </div>
        </div>
          <?php }
          endwhile;
                  echo '<div class="paging">';
                 wp_pagenavi();
                 echo '</div>';
                endif;

So is there a way so that i can first show the posts form reviews and then directory?

回答1:

Finally i got the solution and it can be done using a filter.

The solution looks like this.

add_filter( 'posts_request' , 'modify_request' );
function modify_request( $query) {
    global $wpdb;
    if(strstr($query,"post_type IN ('review', 'directory')")){
        $where = str_replace("ORDER BY {$wpdb->posts}.post_date","ORDER BY {$wpdb->posts}.post_type",$query);
    }
    return $where;
}


回答2:

Order per post types with custom post type order:

add_filter('pre_get_posts', function ($query) {

    if ($query->is_search && !is_admin()) :
        $query->set('post_type', [ 'cpt-1', 'cpt-2', 'post', 'cpt-3']);
    endif;

    return $query;
});



add_filter('posts_orderby', function ( $order ) {

    if ( ! is_admin() ) :

        if ( is_search() && is_main_query() ) :

            global $wpdb;
            $order = "FIELD( post_type, 'cpt-1', 'cpt-2', 'post' ), {$wpdb->posts}.post_modified DESC";      
        endif;

    // Disable this filter for future queries!
    remove_filter( current_filter(), __FUNCTION__);
    endif;

    return $order;
});


回答3:

First solution which comes to my mind is to get posts only for first category. Reset query (wp_reset_query()) and get them again for second category. You need to double up your code of course, but I don't see any other solution - it's WordPress - you're very limited.

Second solution is to query database directly like this:

$result = mysql_query('SELECT * 
FROM  `wp_posts` 
WHERE post_type =  "page"
OR post_type =  "post"
ORDER BY post_type ASC , post_date DESC ');

$posts = array();

if($result) {
    while ($row = mysql_fetch_assoc($result)) {
        $posts[] = $row;
    }
}

mysql_free_result($result);

echo('<pre>');
var_dump($posts);
echo('</pre>');
die();

Notice that I've used post and page types as these are default, and exist in my WP installation. But you can use different. You can play with this query as much as you want.



回答4:

Since Wordpress 4.0 you can just pass the option type (post_type) to the orderby parameter in the WP_Query object.

orderby (string | array) - Sort retrieved posts by parameter. To order by post type just pass:

  • 'type' - Order by post type (available since Version 4.0). ('post_type' is also accepted.)