I've built the following snippet from other post examples that say doing query modification any other way is punishable by great scorn, but it's not working. I'm getting results that include non-published posts and pages which clearly shouldn't happen:
function post_conditions($where)
{
$where .= "AND post_content NOT LIKE '%::exclude tag::%'";
return $where;
}
add_filter('posts_where','post_conditions');
function mysearch($query)
{
$query->set('post_type','post');
$query->set('post_status','publish');
$query->set('posts_per_page',20);
$query->set('paged',get_query_var('paged'));
}
add_action('pre_get_posts','mysearch');
while( have_posts() ){
the_post();
echo get_the_excerpt();
the_tags();
}
if (get_query_var('paged'))
my_paged_function();
wp_reset_query();
The get variables look like so: ?s=mysearchterm&submit=+GO%21+
On my blog template, I'm using the verbotten query_posts() function to achieve the same effect and it works perfectly.
I don't know what's going wrong. Any ideas?
Since this code lives in your template, it's not firing in time to catch the pre_get_posts hook. By the time the template is chosen / running, wp_query is done setting up, and pre_get_posts is over.
You need to move this functionality into your functions.php files, and try and use some other means by which to determine if you want to change the query. There's lots of information available to you - including if it's an archive, a single page, a single post, the post id, and more - hopefully with that information, you can determine if you want to modify the query.
Related
I have created a news dispatches post category. I also created a news releases page, this is the page where I want to show my news dispatches post category posts. How can I show my news dispatches posts in news releases page using post ID or using page permalink in a query? Here is my example code.
add_action('pre_get_posts', 'ad_filter_categories');
function ad_filter_categories($query) {
if ($query->is_main_query() && is_home()) {
$query->set('category_name','news dispatches');
}
}
How can I replace the is_home code line with the page/post ID or the page permalink? Thanks for the help.
Can't use is_page in pre_get_posts (see http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts).
So in the news releases page, add this in:
// Modify the page query
query_posts( 'category_name=news-dispatches');
// The Loop
if ( have_posts() ) {
echo '<ul>';
while ( $have_posts() ) {
the_post();
echo '<li>' . get_the_title() . '</li>';
}
echo '</ul>';
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
UPDATE:
To answer this question: "What php file I am gonna look into to insert this code? ":
It's hard to give exact instructions because it really depends on how your theme is setup.
You need to create a page called page-news-releases.php. See http://codex.wordpress.org/images/1/18/Template_Hierarchy.png for an explanation of page templates. So when wordpress shows the page with the slug news-releases, it will use this file instead of the default.
You'll put my code in this new page for the main loop. You'll also need to look at your other theme files and copy code that needs to go before and after it (for your header and footer and that sort of stuff). It's a little out of the scope of stackoverflow to teach wordpress template design, but hopefully this will get you started. Good luck!
I am working on a WordPress theme. I use a plugin to display pictures on a page (for each post 1 picture), Whenever one of this pictures is clicked the following code registers this and opens a lightbox with the content of the post in it:
<?php
if($_REQUEST['popup']!=''){
$postObj = get_post( $_REQUEST['pid'] );
echo '<div class="ostContent">'.$postObj->post_content.'</div>';
exit;
?>
This all works fine.
Now the problem is that all content get displayed nicely. but for some reason shortcodes don't work. and also when I use a widget in post plugin to display a widget in the post, it doesn't get displayed.
First I tought I needed to enable shortcodes. So I changed this:
echo '<div class="ostContent">'.$postObj->post_content.'</div>';
with this:
echo '<div class="ostContent">'.do_shortcode( $postObj->post_content ).'</div>';
But still nothing. So now I have no idea what to change to make the lightbox show widgets
Hope anyone knows the solution!
EDIT: when I open the post outside the lightbox (by just going to the single page) the shortcode get used like it should be. so somehow the code above don't recognize the shortcode or...
According to a sample here: http://codex.wordpress.org/Function_Reference/do_shortcode
It looks like you need to change: echo '<div class="ostContent">'.do_shortcode( $postObj->post_content ).'</div>';
to:
echo '<div class="ostContent">'.do_shortcode([shortcode_in_brackets]).'</div>';
This should actually display the code. I am assuming that you have defined the actual text in the widget in which the shortcode applies.
Otherwise in the way you currently do it the PHP fires before the post_content even has a value.
I think I understand your problem.
The following should work, assuming the posts in question have a post_type of post:
<?php
// Check for existence of 'popup' & 'pid' query vars
if ( $_REQUEST['popup'] && $_REQUEST['pid'] ) {
// Select single post by ID (using value of the 'pid' query var)
$query = new WP_Query( array ( 'p' => $_REQUEST['pid'] ) );
// Check that the query has returned something
if ($query->have_posts()) {
/* Loop through query until we run out of posts
(should only happen once in this case!) */
while ($query->have_posts()) {
// Setup post, so we can use the_content() and stuff
the_post();
echo '<div class="ostContent">';
/* The part we've been waiting for! the_content() will
display your post content as expected */
the_content();
echo '</div>';
}
}
}
?>
WP_Query is the way to go the majority of the time when needing to retrieve posts: http://codex.wordpress.org/Class_Reference/WP_Query
Your code was retrieving and displaying data almost directly from the WordPress posts table, giving WordPress no chance to apply any of its internal actions and filters (e.g. automatic paragraphs from double line breaks, shortcode execution).
I am reading that query_posts() should be avoided in favor of wp_query() and pre_get_posts(). I am not confident with messing with the Loop and do not fully understand the codex.
Does the code below use query_posts() ? If yes and since query_posts() should be avoided, can you suggest a method that does not use query_posts() but still accomplish the same thing?
This code in functions.php is used to sort posts by random or by price.
function my_custom_query($query){
if ( $query->is_home() && $query->is_main_query() ) {
$sort= $_GET['sort'];
if($sort == "pricelow"){
$query->set( 'meta_key', 'price' );
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'order', 'ASC' );
}
if($sort == "random"){
$query->set( 'orderby', 'rand' );
}
}
}
add_action( 'pre_get_posts', 'my_custom_query' );
.
Link A (Random) and Link B (Price) are posted in my menu by using this code. Thus the visitor to the website can sort the posts simply by clicking a link.
Random
Price
I have done a very detailed explanation on this very topic on WPSE, and for the sake of the value and benefit it might have for SO users, here is the complete post copied from that question on WPSE. For interest sake, here is a link to the complete post on WPSE: Some doubts about how the main query and the custom query works in this custom theme?
Your actual question is basically when to run a custom query and when to make use of the main query. Lets break it down in three parts
PART ONE
When to run a custom query (This is not a definitive list)
To create custom content sliders
To create a featured content area in a page
On page.php templates if you need to display posts
If you require custom content on a static front page
Display related, popular or informational posts
Any other secondary or supplementary content outside the scope of the main query
When to make use of the main query.
To display the primary content on
On your homepage and the page set as a blogpage in the backend
All archive pages which includes templates like archive.php, category.php, author.php, taxonomy.php, tag.php and date.php
PART TWO
To select all the featured posts I use this line that create a new WP_Query object that define a query having the specific tag featured:
So, from what I have understand, this is not the WordPres main query but it is a new query created by me. From what I have understand it is better create a new query (as done) and not use the main query when I want perform this kind of operations
Correct. This falls out of scope for the main query. This is secondary or supplementary content which cannot be created with the main query. You SHOULD ALWAYS use either WP_Query or get_posts to create your custom queries.
NEVER USE query_posts to create custom queries, or even any other query. My emphasis.
Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).
Moving on
Ok, going on I show all the posts that have not the featured tag, to do this I use this code snippet that on the contrary modify the main query:
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
So I think that this is pretty horrible. Is it true?
That is all wrong and your statement is unfortunately true. As said before, NEVER use query_posts. It runs a complete new query, which is bad for performance, and it most cases breaks pagination which is an integral part of the main query for pagination to work correctly.
This is your primary content, so you should be using the main query with the default loop, which should look like this, and this is all you need
<?php
if (have_posts()) :
// Start the Loop.
while (have_posts()) : the_post();
get_template_part('content', get_post_format());
endwhile;
else :
// If no content, include the "No posts found" template.
get_template_part('content', 'none');
endif;
?>
You can completely get rid of this part, delete it, burn it and forget about it
<?
// get the term using the slug and the tag taxonomy
$term = get_term_by( 'slug', 'featured', 'post_tag' );
// pass the term_id to tag__not_in
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
?>
OK, once you've done that, you'll see that posts from the feature tag appear in your home page using the main query and default loop.
The correct way of removing this tag from the homepage is with pre_get_posts. This is the proper way to alter the main query and the hook you should always use to make changes to your primary content loop.
So, the code with pre_get_posts is correct and this is the function that you should use. Just one thing, always do a check that you are not on an admin page because pre_get_posts alters the back end as well. So this is the proper code to use in functions.php to remove posts tagged featured from the homepage
function exclude_featured_tag( $query ) {
if ( !is_admin() && $query->is_home() && $query->is_main_query() ) {
$query->set( 'tag__not_in', 'array(ID OF THE FEATURED TAG)' );
}
}
add_action( 'pre_get_posts', 'exclude_featured_tag' );
PART THREE
Extra reading material which will be helpful in future
Conditional tags
When should you use WP_Query vs query_posts() vs get_posts()?
When to use WP_query(), query_posts() and pre_get_posts
Query Overview
Guidance with The Loop for CMS
Creating a new WP_Query() object is always fine.
$sort= $_GET['sort'];
if($sort == "pricelow"){
$sort_args = array('meta_key' => 'price', 'orderby' => 'meta_value_num', 'order', 'ASC');
$new_query = new WP_Query($sort_args);
}
blah blah blah...
No no no sorry about that. I didn't see the pre_get_posts hook.
The code in your question is good for hooking queries. As in described in WordPress Plugin API/Action Reference/pre_get_posts:
pre_get_posts runs before WP_Query has been setup.
So it hooks the default WP_Query() where you want (in your code, it changes WP_Query on GET request).
In your template files, use new WP_Query($args).
Wordpress Version 3.4.2
I am having a hard time getting the current category name to print on single.php. (outside the loop) There seems to be some sort of caching going on.
I'm trying to do something like this:
if the_category() == 'this posts category' {
echo 'something';
else do this....etc
I've tried several things and always end up with a cached category name. No matter which category the post belongs to.
Here is the snippet that I've been using:
// outside loop
$category = get_the_category();
echo the_category($category[0]->cat_ID);
Alas, it will only print the cached category name, not the category the post is actually in. Thanks for your help. It's really appreciated.
Look at using wp_get_post_categories() instead. maybe something like wp_get_post_categories($post->ID, $args)?
This is a question about Thematic framework. If this isn't the right place, just ignore this.
I'd like to ask how do I go about it? I copied the page template from the parent theme and renamed it to home.php and then I set it as the template for the home page. Then I added a hook to thematic_above_indexloop() in functions.php but it doesn't seem to work. Here's my action hook:
function show_single_post(){
$i=0; // Initialize to Zero;
if (have_posts()) :
while (have_posts()) : the_post();
if ($i==0) {$recentpostid = $post->ID; $i=$i+1;}
endwhile;
endif;
//get only the latest post
$posts = query_posts( 'p='.$recentpostid."'");
}
add_action('thematic_above_indexloop', 'show_single_post');
However, if I embed that code snippet into the home.php directly, it works. There must something wrong with my action hook? I am relatively new to using hooks pls enlighten me.
Since the hello world function works, I have to believe that your function is the problem.
There is a simpler way to get the single latest post:
function show_single_post(){
query_posts('orderby=ID&order=desc&showposts=1');
}
add_action('thematic_above_indexloop', 'show_single_post');
I tested this with Thematic and it shows the last post on the homepage. Give it a shot.
You can check out all the parameters accepted by query_posts on the Codex page
I'm not familiar with Thematic, so I browsed the documentation wiki at http://themeshaper.com/thematic/guide/. I couldn't find the action you reference there. Was it removed from the current version of the framework?
Create a simple "hellow world" function to test if the hook is broken vs your code being broken.
function hello_world(){
echo "hello world";
}
add_action('thematic_above_indeloop', 'show_single_post');
If you see "hello world" on your homepage, you'll know the hook is working. If not, you can be sure (as you probably already are) that your show_single_post function isn't broken.