1
votes

I have a custom page in my theme where I am creating a post from a different DB table and I want to then make this display inside wordpress as if it were a normal post. It seems to work most of the time, but randomly it seems that the post is modified after i call get_header() and i cant see why.

I have setup a mod rewrite rule in apache to hit a php file and in here i get the data I need and build the php object. I populate the wordpress post object using this function.

function BuildSimplePost($title, $body)
{
    require_once( SITEROOT . '/wp-load.php' );
    @$post = new WP_Post();
    @$post->ID = -1; 
    $post->post_parent  = 0;
    $post->post_title = $title;
    $post->post_name = "simple-response";
    $post->post_excerpt = substr($body, 0, 100);
    $post->comment_status = "closed";
    $post->ping_status = "closed";
    $post->post_type = "page";
    $post->post_content = $body;
    return $post;
}

Once the post is sorted I then push this post into the wordpress query objects and let the theme do the rest of the work.

$posts = array($post);
$wp_query->posts = $posts;
$wp_query->post_count = count($posts);
$wp_query->found_posts = count($posts);
$wp_query->max_num_pages = 1;
$wp_query->post = $post;
$wp_query->is_404 = 0;
$wp_query->is_singular = 1;
$wp_query->is_single = 1;
$wp_query->page_id = $post->ID;

include get_template_directory()."/external-page.php";

Inside external-page.php there is nothing weird. It is literally a copy of single.php with some html removed. The issue im having is that when get_header(); is called in this file the post is changed to something else. This then triggers a redirect which brings the user to a different page on the site that is part of wordpress.

Anyone know why the get_header method would be causing a redirect like this?

1
Have you viewed the actual source code that is generated by wordpress.ArtisticPhoenix
@ArtisticPhoenix wordpress has a lot of source code. Can you specify what code i need to look at?Dan Hastings
Not really, but you might see like 2 <head> tags or some really messed up suff, or like a meta refresh who knows unless you look. Maybe you see Easter Bunny there? You don't know what you think you know until you actual know it.ArtisticPhoenix
So you are circumventing all the mechanisms WP has on board for handling custom post types in favor of your own weird flange-mounted through-the-back-door approach ... why exactly?CBroe
also you could try ob_start(); get_header(); $content = ob_get_clean(); that will execute the function but capture the output in the buffer, then you will know if there is some content in the header that is doing it or some functionality. It's a process you just got to eliminate things.ArtisticPhoenix

1 Answers

1
votes

It's hard to tell exactly what's changing up your post. The way I see it, you've got two options:

  1. Keep putting your content back into the post. This is not the WordPress way of solving this problem but it's probably the easier approach. @ArtisticPhoenix's answer above is the right concept but the wrong specific code.
  2. Create a custom post type, which is the WordPress way. @CBroe offered this and the response to your answer to his question should (IMHO) be: "it doesn't matter how complicated your post type is, you should encapsulate it in a CPT if you're using WordPress."

Put your content back

Keep a copy of your post object somewhere and put it back right after anything that changes it. You can create a new global:

global $mypost;
$mypost = BuildSimplePost(...);

If you know the $title and $body parameters, you can just call your function again every time you need it. You could also use a transient, a update_option/get_option call, or several other things.

There are several filters that could be the cuplrit:

  • The the_post action should change $post. That's the one thing it really does. You may want to sit on top of the hook stack like this: add_filter('the_post', function() { global $post, $mypost; $post = $mypost; }, 10000);
  • Before the wp object is set up, there are several actions and you run a high likelihood of anything hooked changing $post because it's free game before then. You may have plugins or your theme hooking on: parse_request, parse_query, pre_get_posts, or posts_selection. You may try something like add_filter('parse_request', function() { global $post; $post = $mypost; }, 10000); for each of these filters.
  • I've seen some plugin developers adding things that change the $post global (and other things they probably shouldn't change) during calls to the actions template_redirect, get_header, loop_start, and after query. Heck, I've done it myself a few times. You could try the same thing with these filters although I'd consider them less suspect.

If that doesn't get your content back, you could try something really dirty, like forcing it in right before the call to the_post. There's no hook for this but if you control the theme it's easy.

The WP Way

I understand that you think that your post is very complicated but I'll offer you this from several years of being neck-deep in WP code: breaking the WP post model is a recipe for heartache. If you're not using posts and you're not using the way they're intended, you probably shouldn't be using WP. There are other frameworks that offer things like user authentication, themeing, database persistence, eventing, REST, etc. without the overhead of WP.

Another way

That having been said, I've used WP in the past because it was part of a requirement that I couldn't control. When my post gets too complicated, I create a wrapper object like so:

class MyPostWrapper {
  private $_Post;
  private $_Meta = array();

  public function __construct($post) {
    $this->_Post = get_post($post);
    $this->_Meta = $this->_LoadMeta();
  }

  private function _LoadMeta() {
    // Load everything into $_Meta: other tables, options, post meta, etc.
  }

  public function __get($name) {
    if (array_key_exists($name, $this->_Meta))
      return $this->_Meta[$name];
  }

  // Use a similar implementation for __set and __isset.

}

However complicated your post gets, you can manage its lifecycle and all of its trail very easily with a single wrapper.

Then you don't have to worry about who's eating your post. If they are, they probably should be.