WordPress.org

Make WordPress Core

Opened 11 years ago

Closed 10 years ago

#6484 closed defect (bug) (invalid)

custom permalinks setting (rewrite.php) causes have_posts function not to work outside of 'the loop'

Reported by: jsherk Owned by:
Milestone: Priority: normal
Severity: normal Version: 2.5
Component: General Keywords:
Focuses: Cc:

Description (last modified by lloydbudd)

This is test code, but I use something similar to display recent posts from multiple blogs on my home page which is external to the wordpress directory.

This code worked on WP 2.3 but when I upgraded to 2.5 it stopped working. If you stick this code in the main wordpress directory, have_posts returns nothing, even though there are posts. If you put in a known exisitng post id, then you will see that it properly displays the post title, but have_posts still says there is nothing!

<?php
require('wp-blog-header.php');
$myid=10; //put a post id here that you know is valid
$mytest = get_post($myid);
echo "Known good post id ".$myid." returns: ".$mytest->post_title;
$mytest = have_posts();
if ($mytest=="") { $mytest="nothing"; }
echo " and have_posts() returns: ".$mytest;
?>

Is this a bug, or has something changed that requires changes to how this works?

Change History (16)

#1 follow-up: @jsherk
11 years ago

Sorry, here is the code from above in a code block:

Okay, just so I know I'm not crazy, try this piece of code:

<?php
require('wp-blog-header.php');
$myid=10; //put a post id here that you know is valid
$mytest = get_post($myid);
echo "Known good post id ".$myid." returns: ".$mytest->post_title;
$mytest = have_posts();
if ($mytest=="") { $mytest="nothing"; }
echo " and have_posts() returns: ".$mytest;
?>

#2 @lloydbudd
11 years ago

  • Description modified (diff)

#3 @markjaquith
11 years ago

  • Resolution set to invalid
  • Status changed from new to closed

have_posts() doesn't know about $mytest. have_posts() is for checking the main $wp_query WP_Query object.

Try this:

<?php
require('wp-blog-header.php');
$myid=10; //put a post id here that you know is valid
$wp_query = new WP_Query( array('p' => $myid ) );
while ( have_posts() ) { the_post(); the_title(); }
?>

If you don't want to disturb the main query, do this:

<?php
require('wp-blog-header.php');
$myid=10; //put a post id here that you know is valid
$my_query = new WP_Query( array('p' => $myid ) );
var_dump(have_posts());
while ( $my_query->have_posts() ) { $my_query->the_post(); the_title(); }
?>

#4 @markjaquith
11 years ago

  • Milestone 2.5.1 deleted

#5 in reply to: ↑ 1 @jsherk
11 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

Okay, I gave a bad example... I was trying to say that there MUST be posts, because when I put a valid ID in, it returns the title, yet have_posts returns empty, when it should in fact return as true or 1. I tried both your examples above...

Example #1 returns a blank browser screen (in both IE6 and FF2).
Example #2 returns bool(false) (in both IE6 and FF2).

HOW TO RECREATE PROBLEM
I copied the code right out of 'the loop' and have_posts still comes up empty. The blog itself works fine... have_posts returns what it should when it is used in the loop. BUT if I copy the same code into a seperate file, and use require('wp-blog-header') then have_posts returns nothing. The problem only occurs when have_posts is in a seperate file (not in the loop).

Sample Code: (needs to be in it's own file like test.php or whatever)

<?php require('wp-blog-header.php'); ?>

<?php if (have_posts()) : ?>

<?php while (have_posts()) : the_post(); ?>

<div class="post" id="post-<?php the_ID(); ?>">
<h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
<small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>

<div class="entry">
<?php the_content('Read the rest of this entry &raquo;'); ?>
</div>

<p class="postmetadata"><?php the_tags('Tags: ', ', ', ''); ?> Posted in <?php the_category(', ') ?> | <?php edit_post_link('Edit', '', ' | '); ?>  <?php comments_popup_link('No Comments »', '1 Comment »', '% Comments »'); ?>

</div>

<?php endwhile; ?>

<div class="navigation">
<div class="alignleft"><?php next_posts_link('&laquo; Older Entries') ?></div>
<div class="alignright"><?php previous_posts_link('Newer Entries &raquo;') ?></div>
</div>

<?php else : ?>

<h2 class="center">Nothing Found</h2>

<?php endif; ?>

Here is the link to the forum where somebody else is having the same problem...
http://wordpress.org/support/topic/164871

---

#6 @lloydbudd
11 years ago

  • Milestone set to 2.6

#7 @andy
11 years ago

  • Resolution set to invalid
  • Status changed from reopened to closed

Not a bug. Inappropriate use of include. WordPress has no facility for guessing what should happen when wp_blog_header.php is included by your script.

The problem is the call to wp(), which assumes the REQUEST_URI is a valid URL or query. If you var_dump($wp) after wp() you'll see that it found a matching pattern but obviously there are no posts found in the "test.php" category.

  ["query_vars"]=>
  array(1) {
    ["category_name"]=>
    string(9) "test2.php"
  }
  ["query_string"]=>
  &string(23) "category_name=test2.php"
  ["request"]=>
  string(9) "test2.php"
  ["matched_rule"]=>
  string(8) "(.+?)/?$"
  ["matched_query"]=>
  string(23) "category_name=test2.php"

The solution: include wp-config.php and then call wp() with query vars.

#8 @Nazgul
11 years ago

  • Milestone 2.6 deleted

#9 @jsherk
11 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

Okay, I could very well be inappropriately using the include, BUT there is still something weird going on (which may be a completely different issue than what I originally posted). I determined that this is somehow related to permalinks.

The following code worked fine in WP2.3 with permalinks set to 'day & name', but does NOT work in WP2.5 with permalinks set 'day & name'. It does however work fine in WP2.5 if I change permalinks back to 'default'. So how does the permalinks setting affect this code working or not working?

<?php
//Displays the title of the 3 most recent posts in the blog
$posts_per_page = 3;
require('./wp-blog-header.php');
if (have_posts()) : while (have_posts()) : the_post();
the_title();
?><br /><?php
endwhile; else:
endif;
?>

#10 @lloydbudd
11 years ago

  • Milestone set to 2.6

#11 @jsherk
11 years ago

  • Summary changed from have_posts does not seem to work outside of the loop to custom permalinks setting causes have_posts function not to work outside of 'the loop'

#12 @westi
11 years ago

One of the greedy rewrites is being matched. Either page or category can be culprits.

You need to add a rewrite rule like the ones for the feed files to make it work I suspect.

Look at how #6460 was fixed and also the original reason those rewrites were introduced #3214

#13 follow-up: @jsherk
11 years ago

  • Summary changed from custom permalinks setting causes have_posts function not to work outside of 'the loop' to custom permalinks setting (rewrite.php) causes have_posts function not to work outside of 'the loop'

I unfortunately don't know enough about rewrite rules to figure out how to do that. I looked at the the fix for #6460, which has no effect on this problem at all.

I did however look at the htaccess files for both 2.3.3 and 2.5 (with custom permalinks enabled) and the htaccess files are identical, but I think it's the rewrite.php file that must be causing the problem...

Problem is fixed when I replace includes/rewrite.php in the 2.5 install with rewrite.php from 2.3.3 (had to comment out line#903 to get it to work).

Sorry that I can't give more details as to what is causing the problem, but I think I've at least narrowed it down.

#14 in reply to: ↑ 13 @hakre
11 years ago

Replying to jsherk:

Sorry that I can't give more details as to what is causing the problem, but I think I've at least narrowed it down.

I think this only points something out on the "level of view" not on the level of what is actual happening.

I strongly discourage moving old codebase into the current one (that is copy over the 2.3.3 file into 2.5).

What needs to be done is a proper analysis here first. If you have problems using version 2.5 stay with 2.3.3 then until these problems are properly fixed. This is at least what I can suggest that sound really solving to me.

#15 @Otto42
11 years ago

Adding a call to "query_posts" would fix this issue in your code.

Essentially, the problem is how the rewrite rules match. In 2.3.3, the rules didn't match anything in your url and so the result was the normal default posts. In 2.5, they match nothing and the result is no posts. The behavior has changed, but that doesn't make the behavior incorrect.

This code:

<?php
require('wp-blog-header.php');
while (have_posts()) {
.. whatever .. 
} ?>

Has always been undefined. The fact that it "just worked" in previous versions is coincidence, not by design. You've not specified what posts should be displayed, and it can't figure it out from the URL rules, so what you get is a bit of a tossup.

If you added a simple query_posts('showposts=3'); to it, then you'd get the latest 3 posts instead, now and forever.

Recommend closing this as invalid. It's not a bug, it's a change in behavior that was previously, and still is, not defined anywhere.

#16 @Denis-de-Bernardy
10 years ago

  • Milestone 2.9 deleted
  • Resolution set to invalid
  • Status changed from reopened to closed

closing this yet again

Note: See TracTickets for help on using tickets.