0

Is it possible to start the loop from a certain post ID? I would like to get all the post starting at a certain ID, decendingly. To explain, I have to make some assumptions first.

Assume that my WordPress database has 20 posts. Obviously, each post will have an ID, and assume that the IDs for those posts posts range from 1, to 20.

Also assume that when we load the posts through the loop, we are using everything by default. So, the loop will retrieve records/posts from 20 to 1. If we have a range restriction of 10, then page 1 will retrieve 20 to 11, and page 2 will retrieve 10 to 1.

Now, back to my question. Assume I would like to recieve records 17 to 8. Can I pass 17 to the loop somehow, and retrieve the 10 records from 17 down to 8? Is this possible?

Here are some lines of code to help understand the issue:

<?php 
    $args = array(
        'post_type'          => 'post',
        'post_status'        => 'publish',
        'category_name'      => 'news',
        'posts_per_page'     => 10,

        'ID_VARIABLE_HERE'   => 17 // I would like to be able to pass the ID, and the loop should return 10 posts (as defined in the posts_per_page), descendingly, starting at 17. 

    );



    $custom_query = new WP_Query($args);

?>  

<?php if ($custom_query->have_posts()): while ($custom_query->have_posts()) : $custom_query->the_post() ; ?>

    <article class="my-article">

        <div class="my-image"><?php the_post_thumbnail(); ?></div>

        <div class="my-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></div>

        <div class="my-details"><?php the_excerpt(); ?></div>

    </article>

<?php endwhile; else: ?>
    <p><?php _e('No contents exist.'); ?></p>
<?php endif; ?>

As you can see, I would like to pass an argument, in the $args, that will have the ID value (17 in the example above). Read the code comment above for details of what is needed. Is it possible? If not via an argument in $args, what is another way of doing that?

Thanks.

  • Can you please add more details to your question? as explanatory as possible. In this instance an example would also help – Maruti Mohanty Mar 5 '14 at 6:12
  • @MarutiMohanty: I just did, plese review the edit. Thanks. – Greeso Mar 5 '14 at 7:10
  • Do you have some code that you're working with? – Stephen S. Mar 5 '14 at 23:24
  • @StephenS. I updated the question. – Greeso Mar 5 '14 at 23:58
1

You can use posts_where hook to achieve this

add_filter( 'posts_where' , 'posts_where' );

function posts_where( $where ) {

    global $wpdb;

    $start = $query->get('ID_VARIABLE_HERE');
    // add any condition if you have
    if ( ! is_admin() && $query->is_main_query()){

        $where .= " AND {$wpdb->posts}.ID >= $start";
    }
    return $where;
}
0

Would using the offset parameter work for your needs?

$args = array(
    'post_type'          => 'post',
    'post_status'        => 'publish',
    'category_name'      => 'news',
    'posts_per_page'     => 10, 
    'offset'             => 17
);
  • No, not really. I looked into it already. Offset is not and ID. In the example above, offset would start at post with ID 3 (which is the start ID of 20 minus 17 offset posts) rather than 17. – Greeso Mar 6 '14 at 19:12
0

You can do something like below providing the post id which you want to start as the $max_post_id and descending down to a certain post_id which can be provided as $min_post_id:

// Get all post ids.
$all_post_ids = get_posts(array(
    'fields'          => 'ids', // Only get post IDs
    'posts_per_page'  => -1
));

// Make a list of all possible post ids between two post ids.
$max_post_id = 17;
$min_post_id = 8;
$custom_post_id = [];
for ( $i = $max_post_id; $i > $min_post_id; $i-- ) {
    $custom_post_id[] = $i;
}

// Filter out the valid post ids from the possible post ids.
$query_post_ids = array_intersect( $custom_post_id, $all_post_ids );

$args = array(
    'post_type'      => 'post',
    'post_status'    => 'publish',
    'category_name'  => 'news',
    'posts_per_page' => 10,
    'post__in'       => $query_post_ids // Use the valid post ids in the array.
);

$custom_query = new WP_Query( $args );

if ( $custom_query->have_posts() ):
    while ($custom_query->have_posts()) :
        $custom_query->the_post() ; ?>

        <article class="my-article">

            <div class="my-image"><?php the_post_thumbnail(); ?></div>

            <div class="my-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></div>

            <div class="my-details"><?php the_excerpt(); ?></div>

        </article>

    <?php
    endwhile;
else: ?>
    <p><?php _e('No contents exist.'); ?></p>
<?php endif;

Note that this may create performance issue since we are using "for" loop to create possible ids with decrement of 1 if the gap between max and min is too big.

0

There is a way to do it with pre_get_posts and WP_Query with a custom parameter ! :)

Assume this is our $args.

$args = array(
    'post_type'          => 'post',
    'post_status'        => 'publish',
    'category_name'      => 'news',
    'posts_per_page'     => 10,

    'maximum_id'         => 17, // I choose this name for example, feel free
);

You'll have to catch the maximum_id parameter in pre_get_posts hook.

function wpse_136861_pre_get_posts($query) {
    if(intval($query->get('maximum_id')) > 0 && $query->get('maximum_id') >= $query->get('posts_per_page'))
    {
        $start = $query->get('maximum_id') - $query->get('posts_per_page');

        // Be sure to avoid the negative / 0 value
        if($start <= 0)
        {
            $start = 1;
        }

        $end = $query->get('maximum_id');

        $query->set('post__in', range($start, $end)); // Set your post_id array with all int beetween $start and $end (7-17 here)
        $query->set('orderby', 'ID'); // Set by ID DESC (DESC order is default in WP_Query)
    }
    return $query;
}
add_action('pre_get_posts', 'wpse_136861_pre_get_posts');

This works :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.