Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a custom-post-type archive (archive-rg_blog.php) with two loops in it. One of the loops I'd like to filter with the below code. It's just a basic loop for all posts, and I just need to set it to return all posts instead of the custom posts it'd return by default.

The other loop needs to pull the title and content from a specific custom post. The below seems to be filtering the second loop too, and so that it returns nothing at all.

function blog_filter($query) {
  if ( !is_admin() && $query->is_main_query() ) {
    if ($query->is_post_type_archive('rg_blog')) {
      $query->set('post_type', 'post');
    }
  }
}
add_action('pre_get_posts','blog_filter');

And this is the loop that returns nothing:

<?php // blog title and description query
$post_id = 4606;
$queried_post = get_post($post_id);
$title = $queried_post->post_title;?>
<h1><?php echo $title;?></h1>

Edit: Just to clarify, this is what I'm trying to do.

///loop 1, queries a specific post
///loop 2, a normal loop filtered with pre_get_posts, which should return all posts.
///loop 3, also queries a specific post

So I need to add the filter before loop 2, and remove it again before loop 3. I've tried to add the filter into the archive template in the appropriate place, but loop 2 then fails to return all posts.

Edit #2: Here's the whole loop in action. It's the SECOND loop that needs to be filtered.

<?php get_header(); ?>

<?php // blog title and description query
$post_id = 4606;
$queried_post = get_post($post_id);
$title = $queried_post->post_title;?>
<h1><?php echo $title;?></h1>

<!-- Main Loop (All Posts)   -->
<?php function blog_filter($query) {
  if ( !is_admin() && $query->is_main_query()) {
    if ($query->is_post_type_archive('rg_blog')) {
      $query->set('post_type', 'post');
    }
  }
}
add_action('pre_get_posts','blog_filter');?>
<?php $post = $posts[0]; $c=0;?>
<?php if (have_posts()) : ?><?php while (have_posts()) : the_post(); ?>
<!--Featured Post-->
<?php $c++;
if( !$paged && $c == 1) :?>
<!--stuff-->
<!--Other Posts-->
<?php else :?>           
<!--the remaining posts-->          
<?php endif;?>
<?php endwhile; endif; ?>
<!-- The end of the loop   -->
<?php remove_action('pre_get_posts','blog_filter');?>

        <!--third loop, a repeat of loop 1-->  
<?php // blog title and description query
$post_id = 4606;
$queried_post = get_post($post_id);
$title = $queried_post->post_title;?>  
                <h1><?php echo $title;?></h1>
                <?php echo $queried_post->post_content;?>
<?php get_footer() ?>
share|improve this question
    
I know I pointed you down this road in a previous question, but the premise of what you're doing here is flawed. first, your pre_get_posts action and function go in your theme's functions.php. the main query runs before the template is loaded, so nothing will happen if you try to apply it in the template. HOWEVER- changing the post type of the main query will cause the query to no longer be a custom post type archive, so your archive-rg_blog.php template will never get loaded. Can you not do what you want by simply creating a page and making that the posts page under settings > reading? –  Milo Jul 11 '13 at 1:16
    
Maybe. I'll give that a try. –  Josh Jul 11 '13 at 1:26
add comment

2 Answers

Add the filter where you need it and remove it afterwards.

add_action('pre_get_posts','blog_filter');
// your query; presumably WP_Query
// your first loop
remove_action('pre_get_posts','blog_filter');
// another query; presumably WP_Query
// your second loop

You can also make your action self-removing:

function blog_filter($query) {
  remove_action('pre_get_posts','blog_filter');
  if ( !is_admin() && $query->is_main_query() ) {
    if ($query->is_post_type_archive('rg_blog')) {
      $query->set('post_type', 'post');
    }
  }
}
add_action('pre_get_posts','blog_filter');

Your code, reorganized:

// define the function; can be here or functions.php
function blog_filter($query) {
  if ( !is_admin() && $query->is_main_query()) {
    if ($query->is_post_type_archive('rg_blog')) {
      $query->set('post_type', 'post');
    }
  }
}

get_header(); 

  // blog title and description query
  $post_id = 4606;

  // add the filter
  add_action('pre_get_posts','blog_filter'); 

  $queried_post = get_post($post_id);

  // remove the filter; the query is done
  remove_action('pre_get_posts','blog_filter'); 

  $title = $queried_post->post_title; ?>
  <h1><?php echo $title;?></h1><?php

  // Main Loop (All Posts)
  $post = $posts[0];
  $c=0;
  if (have_posts()) {
    while (have_posts()) {
      the_post(); 
      // Featured Post
      $c++;
      if( !$paged && $c == 1) {
        // stuff 
        // Other Posts
      } else {           
        // the remaining posts          
      }
    }
  }
  // The end of the loop
  // third loop, a repeat of loop 1

  // blog title and description query
  $post_id = 4606;
  $queried_post = get_post($post_id);
  $title = $queried_post->post_title; ?>  
  <h1><?php echo $title;?></h1><?php 
  echo $queried_post->post_content;
get_footer();

I have not tested that but I think it will work better. Hopefully, I don't have any syntax errors.

Edit:

I took a closer look at your code (while not watching "Defiance") and notices a couple of things.

  1. Your filter will only effect the main query so you will need to add it before the page template loads-- probably in functions.php. But my understanding of the question is that the filter is meant for a secondary Loop. That would mean that that "main query" check is wrong.
  2. You are requesting posts via get_post by ID, so for those the filter is irrelevant.

So, to filter that main query you need this in functions.php:

// define the function; can be here or functions.php
function blog_filter($query) {
  // remove the filter; the query is done
  remove_action('pre_get_posts','blog_filter');
  if ( !is_admin() && $query->is_main_query()) {
    if ($query->is_post_type_archive('rg_blog')) {
      $query->set('post_type', 'book');
    }
  }
}
add_action('pre_get_posts','blog_filter'); 

And no add or remove actions anywhere else. I am not sure that is what you want though. The two get_post calls should be unaffected.

share|improve this answer
    
I am trying to add and remove the filter where needed, but it doesn't seem to work. Do I register the function in the functions.php file and then add the filter in the archive file, or does the whole thing go in the archive file? –  Josh Jul 10 '13 at 23:56
    
See my edit above, which clarifies exactly what I'm trying (and failing) to do. –  Josh Jul 11 '13 at 0:05
    
See the edit, and post all of your code so I can see it in context. –  s_ha_dum Jul 11 '13 at 0:20
    
Okay, see my new edit. –  Josh Jul 11 '13 at 0:45
    
Like said, you have to add the filter before the query. Give me a minute to reorganize that. –  s_ha_dum Jul 11 '13 at 1:41
show 3 more comments

I would suggest checking the is_post_type_archive before adding the filter:

global $wp_query;
if ($wp_query->is_post_type_archive('rg_blog')) {
    add_action('pre_get_posts','blog_filter');
}

This way, it won't run on every page load.


Try removing the filter before the second query:

remove_action('pre_get_posts', 'blog_filter');
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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