Why is 'pre_get_posts' having no effect?

I’m trying to use pre_get_posts for the first time without any success. It’s a very simple piece of code on the index page of an otherwise empty theme, purely to get the hang of the action hook:

function just_one( $query )
{
    $query->set( 'posts_per_page', 1 );
}
add_action( 'pre_get_posts', 'just_one' );

From what I have read, I cannot see anything wrong with this, but when I run this below it:

echo get_query_var( 'posts_per_page' );

it displays the default ’10’, rather than the ‘1’ I was expecting. Am I doing something wrong? The index page is entirely empty apart from the above code. Cheers for any help.

Solutions Collecting From Web of "Why is 'pre_get_posts' having no effect?"

… It’s a very simple piece of code on the index page of an
otherwise empty theme…

If you are running this code on the index page of your theme and expect it to effect the main query, then you are adding the action too late. The main query runs well before your theme template loads. You will need to put that code in functions.php in your active theme or in a plugin and use some conditional logic to make sure that it runs only where you want it too. For example…

function just_one( $query ) {
  if ( $query->is_main_query() && $query->is_front_page() ) {
    $query->set( 'posts_per_page', 1 );
  }
}
add_action( 'pre_get_posts', 'just_one' );

I don’t really know what the if condition should be. Refer to the Codex page already linked to for the conditions available.

Try this instead. You always need to check for the main_query

function just_one( $query )
{
    if ( $query->is_main_query() ) {
        $query->set( 'posts_per_page', 1 );
    }
}
add_action( 'pre_get_posts', 'just_one' );