WordPress: Creating a Fake Post with a Plugin

Tutorials Add comments

Recently a plugin author released a cool little plugin that creates a more dynamic “About Me” style page. When the plugin is activated, it will create a physical page in the database. The content of that page would have some PHP function calls for the author’s plugin. This plugin also required the Exec-PHP plugin to be installed, so that the PHP function calls in the page could be executed.

There is a better way though! A better way than actually creating a page with PHP code in it, and requiring the Exec-PHP plugin. The author’s plugin could simply create a fake page. A page that doesn’t actually exists in the database, but is viewable, and indexable by search engines.

Here is the code for making this happen.

<?php
/**
 * Plugin Name: Fake Page Plugin
 * Description: Creates a fake page
 * Author: Sean Hickey
 * Version: 1.0
 */
 
class FakePage
{
	/**
	 * The slug for the fake post.  This is the URL for your plugin, like:
	 * http://site.com/about-me
	 * @var string
	 */
	var $page_slug = 'about-me';
 
	/**
	 * The title for your fake post.
	 * @var string
	 */
	var $page_title = 'About Me';
 
	/**
	 * Allow pings?
	 * @var string
	 */
	var $ping_status = 'open';
 
	/**
	 * The template file that will be used when displaying your fake post.
	 */
	var $template_page = 'single.php';
 
	/**
	 * Class constructor
	 */
	function FakePage()
	{
		/**
		 * We'll wait till WordPress has processed the query vars, and then
		 * start rockin' and rollin'.
		 */
		add_action('parse_query', array(&$this, 'Init'));
	}
 
	/**
	 * Called by the 'parse_query' action
	 */
	function Init()
	{
		global $wp_query; // <-- Important query stuff in here
 
		/**
		 * Now this works with permalinks, or regular ol' ?page_id= URLs.
		 * What we're checking for is the name of the post requested by
		 * the visitor.
		 * The first part: $wp_query->get('name') == $this->page_name  is
		 * for when permalinks are being used.
		 * The second part: $wp_query->query_vars['page_id'] == $this->page_name
		 * is for when regular URLs are being used.  That would be a URL
		 * like:  http://mysite.com/?page_id=about-me
		 * If we've found the post we're looking for, then add an action
		 * for when WordPress goes to load the template file.
		 */
		if ($wp_query->get('name') == $this->page_slug || $wp_query->query_vars['page_id'] == $this->page_slug) {
			add_action('template_redirect', array(&$this, 'TemplateRedirect'));
		}
	}
 
	/**
	 * Called by the 'template_redirect' action
	 */
	function TemplateRedirect()
	{
		global $wp_query;
 
		/**
		 * Make sure the user selected template file actually exists.  If
		 * not we're kinda screwed.
		 */
		if (file_exists(TEMPLATEPATH . '/' . $this->template_page)) {
 
			/**
			 * What we are going to do here, is create a fake post.  A post
			 * that doesn't actually exist. We're gonna fill it up with
			 * whatever values you want.  The content of the post will be
			 * the output from your plugin.  The questions and answers.
			 */
 
 
			/**
			 * Clear out any posts already stored in the $wp_query->posts array.
			 */
			$wp_query->posts = array();
			$wp_query->post_count = 0;
 
			/**
			 * Create a fake post.
			 */
			$post = new stdClass;
 
			/**
			 * The author ID for the post.  Usually 1 is the sys admin.  Your
			 * plugin can find out the real author ID without any trouble.
			 */
			$post->post_author = 1;
 
			/**
			 * The safe name for the post.  This is the post slug.
			 */
			$post->post_name = $this->page_slug;
 
			/**
			 * Not sure if this is even important.  But gonna fill it up anyway.
			 */
			$post->guid = get_bloginfo('wpurl') . '/' . $this->page_slug;
 
 
			/**
			 * The title of the page.
			 */
			$post->post_title = $this->page_title;
 
			/**
			 * This is the content of the post.  This is where the output of
			 * your plugin should go.  Just store the output from all your
			 * plugin function calls, and put the output into this var.
			 */
			$post->post_content = $this->GetContent();
 
			/**
			 * Fake post ID to prevent WP from trying to show comments for
			 * a post that doesn't really exist.
			 */
			$post->ID = -1;
 
			/**
			 * Static means a page, not a post.
			 */
			$post->post_status = 'static';
 
			/**
			 * Turning off comments for the post.
			 */
			$post->comment_status = 'closed';
 
			/**
			 * Let people ping the post?  Probably doesn't matter since
			 * comments are turned off, so not sure if WP would even
			 * show the pings.
			 */
			$post->ping_status = $this->ping_status;
 
			$post->comment_count = 0;
 
			/**
			 * You can pretty much fill these up with anything you want.  The
			 * current date is fine.  It's a fake post right?  Maybe the date
			 * the plugin was activated?
			 */
			$post->post_date = current_time('mysql');
			$post->post_date_gmt = current_time('mysql', 1);
 
 
 
			/**
			 * Now add our fake post to the $wp_query->posts var.  When "The Loop"
			 * begins, WordPress will find one post: The one fake post we just
			 * created.
			 */
			$wp_query->posts[] = $post;
			$wp_query->post_count = 1;
 
			/**
			 * And load up the template file.
			 */
			load_template(TEMPLATEPATH . '/' . $this->template_page);
 
			/**
			 * YOU MUST DIE AT THE END.  BAD THINGS HAPPEN IF YOU DONT
			 */
			die();
		}
	}
 
	function GetContent()
	{
		return '<p>Hi there!  You are viewing my fake post!</p>';
	}
}
 
/**
 * Create an instance of our class.
 */
new FakePage;
?>

Using the above code, when someone visits the URL http://site.com/about-me (or http://site.com/?page_id=about-me), your plugin
takes over. It then creates a new fake post, and adds it to the $wp_query vars. When the single.php template is loaded, that one single fake post will be displayed.

This example will just show a fake post with the title About Me, and the content of the post will be “Hi there! You are viewing my fake post!”.

You can easily change the GetContent() method to whatever you want. Whatever is returned by the method will be the fake post’s content.

Enjoy!
To copy the code from above.

15 Responses to “WordPress: Creating a Fake Post with a Plugin”

  1. ScottS-M Says:

    Thanks for the great tutorial. I modified the code a bit to fix the 404 error. It ended up being more changes than I could easily leave in a comment so I posted them here. Hope that’s ok. Thanks again.

  2. ScottS-M Says:

    Oops looks like no links from inside the comments. I put the address in this comment’s website field. Sorry about the comment clutter.

  3. Jim Says:

    I don’t understand – why would anyone actually want to create a fake page? What are the advantages to doing such a thing?

  4. j4p4n Says:

    If you would call that fake post “guestbook” or something likely, you could build a bot-trap (bots love guestbooks =D) just by using a plugin.

  5. Sean Says:

    @Jim – Like I said at the top of the post, some plugins require their own page, or post. The Ask Me plugin is one of many – http://www.wpplugins.org/plugin/ask-me

    The plugin lets users ask the blogger questions, and when the blogger responds to those questions, the Q&A appears on the blogger’s “Ask Me” page.

    An example – http://ilovecode.com/qanda/

    When this plugin is activated, it physically creates a page in the user’s database. That page has a few Ask Me function calls inside of it, wrapped up in some tags that tell Exec-PHP to execute those function calls.

    The purpose behind this post is to show how you can forget the page creation process altogether. Your plugin can intercept a specific permalink request (in this case site.com/about-me), and display whatever your plugin is supposed to display on the page. There’s no need to actually create a real page.

  6. Sean Says:

    I may not have made this perfectly clear, but the reason for taking this approach, is because you want WordPress to do the work of displaying your plugin’s output. With that, your plugin’s output will match the user’s selected theme.

    You could simply catch the permalink, and spit out some HTML. But then that HTML wouldn’t match up with the user’s theme. So by taking this approach, your content integrates perfectly into the user’s blog.

  7. Dave Says:

    This is a really cool idea. One reason I’d want to use it is to be able to use pure PHP in my posts, as opposed to WordPress-processed PHP. For example, try using the “next” tag in the middle of a PHP function in a post. It doesn’t work. Another use is if you want to have pages that break WordPress rules. For example, WordPress doesn’t allow page slugs of “search” or “comments”. With this plugin, you could potentially do that.

    But Sean, I’m having a problem. When I make a fake page, it only works when I call it with “?page_id=”. The slug doesn’t work (site.com/slug/). Any ideas? Rewriting is enabled on my site.

  8. Sean Says:

    @Dave,
    The method hasn’t been fully explored yet. I can tell you that the current implementation requires the use of your site’s permalink structure.

    That means if you site is using a permalink structure like this:

    site.com/2007/01/01/name-of-post

    Then you would access the fake post using a similar structure, like:

    site.com/2007/01/01/about-me

    I’m sure there is a work around, and I’ll look into it.

  9. Sean Says:

    Okay, found a work around, and the rewritten code from above is here:

    http://bin.headzoo.com/bin/53

  10. Dave Says:

    Awesome. That works. Excellent work.

  11. BillSaysThis Says:

    Another nice aspect of this implementation, which Sean is cearly too modest to mention, is that you can use PHP’s OO inheritance capabilities to create multiple versions/pages by subclassing FakePage once for each page and simply changing the class variables and making a new GetContent function. This is a very clean implementation, nice work Sean.

  12. Jeriko One Says:

    Does this also work for pseudo-permalinks? (like hxxp://domain.tld/index.php/year/month/pageslug?

  13. Vasya Says:

    preved ot slesarya Vasi

  14. Nick Says:

    Hi,
    I’ve tried this and found that if you test the page with a basic browser (specifically: try lynx) wordpress actually responds with a “404 page not found header” before delivering the page content.

    The page “appears” to work find in firefox but the header is still there, you then run into issues when submitting the page to validator service (or similar) as it sees the “404″ and has an error.

    Do you know how to fix this ?
    Cheers,
    Nick

  15. chada Says:

    It is really a good idea, what I learn from this is that we CAN combain some other applications to it, eg.,gallery.

    P.S. I had translated it into Chinese and posted it on my blog

    Thanx!

Leave a Reply

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in