web-dev-qa-db-fra.com

Comment lister quelques posts en premier sur la boucle en fonction de post id

J'ai une requête pour afficher certains messages.

$args = array(
    'post_type' =>'products'
    'posts_per_page'=> 12,
    'orderby'       => 'meta_value_num',
    'meta_key'  => '_price',
    'order' => 'asc',
);
$loop=new WP_Query($args); 
while($loop->have_posts()) : $loop->the_post();
    the_content();
endwhile;

Dans cette boucle, je récupère les produits, mais je dois d'abord afficher certains produits dans cette boucle. 12,13,14,34 Ce sont mes identifiants de publication que je dois d'abord afficher dans la boucle.

Comment puis-je afficher ce message en premier et laisser les autres? . Y a-t-il un moyen de faire ça . Si une variable dans les $ args supportait ce type de fonctionnalité?

6
Ron

Si vous avez besoin:

  • paginer la requête

  • conservez 12 posts par page au lieu de "coller" les posts souhaités au-dessus des 12 requis

  • seulement besoin d'afficher ces messages sur la première page

vous pouvez essayer ce qui suit

$ids_args = [
    'post_type'      => 'products'
    'posts_per_page' => -1,
    'orderby'        => 'meta_value_num',
    'meta_key'       => '_price',
    'order'          => 'ASC',
    'fields'         => 'ids'
];
$all_posts_ids = get_posts( $ids_args );

// Make sure we have posts before continuing
if ( $all_posts_ids ) {
    // Set all our posts that should move to the front 
    $move_to_front   = [12,13,14,34];
    // Add the array of posts to the front of our $all_posts_ids array
    $post_ids_merged = array_merge( $move_to_front, $all_posts_ids );
    // Make sure that we remove the ID's from their original positions
    $reordered_ids   = array_unique( $post_ids_merged );

    // Now we can run our normal query to display 12 posts per page
    $args = [
        'post_type'      => 'products'
        'posts_per_page' => 12,
        'post__in'       => $reordered_ids,
        'orderby'        => 'post__in',
        'order'          => 'ASC',
        'paged'          => get_query_var( 'paged', 1 ),
    ];
    $loop = new WP_Query( $args ); 
    while( $loop->have_posts() ) {
        $loop->the_post();
            the_content();
    }
    wp_reset_postdata();
}

Si vous avez besoin de ces messages

  • coller au-dessus des 12 articles sur chaque page

  • dans une requête paginée

vous pouvez exécuter deux requêtes comme suit

// Set an array of id's to display in front
$move_to_front   = [12,13,14,34];
// Run the query to display the posts you need in front
$args_front = [
    'post_type'      => 'products'
    'posts_per_page' => count( $move_to_front ),
    'post__in'       => $move_to_front,
    'orderby'        => 'meta_value_num',
    'meta_key'       => '_price',
    'order'          => 'ASC',
];
$loop_front = new WP_Query( $args_front );
if( $loop_front->have_posts() ) {
    while( $loop_front->have_posts() ) {
        $loop_front->the_post();
            the_content();
    }
    wp_reset_postdata();
}

// Now we can run our major loop to display the other posts
$args = [
    'post_type'      => 'products'
    'posts_per_page' => 12,
    'post__not_in'   => $move_to_front,
    'orderby'        => 'meta_value_num',
    'meta_key'       => '_price',
    'order'          => 'ASC',
    'paged'          => get_query_var( 'paged', 1 ),
];
$loop = new WP_Query( $args );
if( $loop->have_posts() ) {
    while( $loop->have_posts() ) {
        $loop->the_post();
            the_content();
    }
    wp_reset_postdata();
}

Si vous n'avez besoin que d'une page avec ces publications au premier plan, la solution de @birgire fera parfaitement l'affaire.

7
Pieter Goosen

Nous pourrions le faire avec deux requêtes:

Tout d'abord, nous extrayons les identifiants de publication dont nous avons besoin avec la première requête, puis nous les fusionnons avec nos identifiants de post-it collants et nous l'insérons dans la seconde requête, en utilisant le paramètre post__in pour le filtrage et la commande:

$args = [
    'post_type'           => 'products'
    'posts_per_page'      => 12,
    'orderby'             => 'meta_value_num',
    'meta_key'            => '_price',
    'order'               => 'asc',
    'ignore_sticky_posts' => true,
    'fields'              => 'ids',
];
$ids = get_posts( $args );
if( ! empty( $ids ) )
{
    $stickies = [12,13,14,34];
    $post__in = array_unique( array_merge(  $stickies, $ids ) );
    $args = [
        'post__in'            => $post__in,
        'orderby'             => 'post__in',
        'ignore_sticky_posts' => true,
    ];
    $loop = new WP_Query( $args ); 
    // ... etc
}

où nous ajustons le $stickies pour les posts collants personnalisés.

4
birgire

La solution de Birgire ne fonctionnait pas vraiment pour moi telle quelle. Je devais spécifier un post_type‍ dans mes arguments après le tri.

Voici mes modifications, construites en classe.

class locations{

  public function __construct(){
    $this->args = [
      'post_type'           => 'location',
      'posts_per_page'      => -1,
      'orderby'             => 'title',
      'order'               => 'asc',
      'fields'              => 'ids',
      'ignore_sticky_posts' => true,
    ];
    $this->ids = get_posts($this->args);
    $this->get = new WP_Query($this->sort_ids());
  }

  //Sorts the locations by specified criteria
  private function sort_ids(){
    $stickies = [2071,2080,2069,1823];
    $post__in = array_unique(array_merge($stickies, $this->ids));
    $args = [
        'post_type'           => 'location',
        'post__in'            => $post__in,
        'orderby'             => 'post__in',
        'order'               => 'asc',
        'posts_per_page'      => -1,
        'ignore_sticky_posts' => true,
    ];
    return $args;
  }
}
0
Alex Standiford