You can set the orderby to post__in. Here is a superior post loop:
$args = [
'post__in' => [ 1, 2, 3, 4 ],
'orderby' => 'post__in',
];
$q = new \WP_Query( $args );
if ( $q->have_posts() ) {
while ( $q->have_posts() ) {
$q->the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php the_title(); ?>
</article>
<?php
}
wp_reset_postdata();
} else {
echo '<p>No posts found</p>';
}
Important changes:
get_postsdoes not fire all the loop lifecycle filters, bypasses caches by default (suppress_filtersis set to true inget_posts), and doesn’t set the current post for you. It also usesWP_Queryinternally, so I cut out the middleman and usedWP_Querydirectly. This loop is both faster, more expandable, and more compatible- I removed
numberpostsandpost_type, these are unnecessary and would actually slow down the query if WP used them. WP knows which posts you want viapost__inso it’ll just fetch those orderbyis set topost__inso posts will appear in the same order they’re requested- I used a PHP array instead of using
explodeon a string ( which gives the same result so why do the extra work? ) - I used
the_IDandpost_classso the inner loops tags would have the appropriate classes
I strongly recommend you read through this document: https://developer.wordpress.org/reference/classes/wp_query/ it will save a lot of time in the future and has a lot of examples.