web-dev-qa-db-fra.com

Comment renvoyer les résultats d'un get_posts () dans un ordre explicitement défini

J'essaie de créer une boucle de posts à commande explicite, par exemple:

<?php $args = array(
    'include'         => '1,3,8,4,12' ); ?>

<?php get_posts( $args ); ?> 

Les résultats sont classés par date par défaut et il n’existe pas d’option orderby pour renvoyer les publications dans l’ordre dans lequel elles ont été entrées. Plusieurs demandes de bogues/fonctionnalités ont été postées à ce sujet dans Trac, mais jusqu'à présent, aucune chance. Je me suis un peu mucked dans les fichiers de base, mais je ne suis allé nulle part avec.

Quelqu'un peut-il suggérer une solution de contournement pour ce comportement?

À la vôtre, Dalton

5
Dalton

D'accord, j'étais déterminé à trouver un moyen de faire cela, et je pense l'avoir. J'avais espéré trouver une solution plus simple et éviter de devoir utiliser un nouvel objet WP_Query, mais c'est trop enraciné dans le fonctionnement de la boucle. Premièrement, nous avons quelques fonctions d’utilité:

// Set post menu order based on our list  
function set_include_order(&$query, $list) {
    // Map post ID to its order in the list:
    $map = array_flip($list);

    // Set menu_order according to the list     
    foreach ($query->posts as &$post) {
      if (isset($map[$post->ID])) {
        $post->menu_order = $map[$post->ID];
      }
    }  
}

// Sort posts by $post->menu_order.                                 
function menu_order_sort($a, $b) {
  if ($a->menu_order == $b->menu_order) {
    return 0;
  }
  return ($a->menu_order < $b->menu_order) ? -1 : 1;
}

Cela nous permettra de définir la propriété menu_order en fonction de notre propre liste, puis de trier les publications dans un objet de requête en fonction de celle-ci.

Voici comment nous interrogeons et trions les messages:

$plist = array(21, 43, 8, 44, 12);
$args = array(
  'post_type' => 'attachment',
  'post_status' => 'any',
  'post__in' => $plist 
);

// Create a new query  
$myquery = new WP_Query($args);

// set the menu_order
set_include_order($myquery, $plist);

// and actually sort the posts in our query
usort($myquery->posts, 'menu_order_sort');

Nous avons donc maintenant notre propre objet de requête, et le $myquery->posts est trié selon notre fonction personnalisée menu_order_sort. La seule partie délicate à présent est que nous devons construire notre boucle en utilisant notre objet de requête personnalisé:

while($myquery->have_posts()) : $myquery->the_post();
  ?>
    <div><a id="post_id_<?php the_ID(); ?>" class="nb" href="<?php the_permalink(); ?>"><?php the_title(); ?></a> Post ID: <?php the_ID(); ?>
    </div>
  <?php

endwhile;
wp_reset_postdata();

Évidemment, vous corrigeriez le code du modèle de boucle ici.

J'espérais trouver une solution qui ne nécessiterait pas l'utilisation d'un objet de requête personnalisé, peut-être en utilisant query_posts() et en remplaçant la propriété posts sur le $wp_query global, mais je ne pouvais tout simplement pas le faire fonctionner correctement. Avec un peu plus de temps pour y travailler, cela aurait pu être faisable.

Quoi qu'il en soit, voyez si cela vous mènera là où vous devez aller?

6
Dougal Campbell

Vous pouvez essayer ceci:

add_filter('posts_orderby', 'enforce_specific_order');
$posts = get_posts($args);
remove_filter( current_filter(), __FUNCTION__ );

function enforce_specific_order($orderby) {
    global $wpdb;
    return "FIND_IN_SET(".$wpdb->posts.".ID, '1,3,8,4,12') ASC";
}
10
wyrfel

Je pense que c'est le moyen le plus rapide de renvoyer les résultats d'un get_posts dans un ordre défini. Et à part ça, c'est une solution native, sans piratage

<?php

$posts_order = array('1,3,8,4,12');
$args = array(
    'post__in' => $posts_order,
    'orderby' => 'post__in'
); 
get_posts( $args ); 

?> 
6
Pablo S G Pacheco

À partir de WordPress 3.5, cette fonctionnalité est maintenant au cœur. Vous pouvez explicitement commander des publications en utilisant le paramètre "post__in". http://core.trac.wordpress.org/ticket/13729

3
Dalton

Pourquoi ne pas effacer la orderby avec un filtre? Juste avant de consulter vos publications, insérez:

add_filter('posts_orderby', '__return_false');

Ensuite, une fois votre boucle terminée:

remove_filter('posts_orderby', '__return_false');

Si vous supprimez à nouveau le filtre, c’est au cas où il y aurait d’autres boucles sur la page (comme des widgets) qui nécessiteraient leur ordre explicite normal.

0
Dougal Campbell