I’m currently developing a WordPress plugin that needs to show a virtual page generated by my plugin (such as a form or a message) and I wanted to avoid adding a new Page and modifying the current WordPress installation, so every plugin form, message or page had to be generated on the fly without touching the database.
Some WordPress plugins or themes create new pages in the website’s installation to add advanced functionalities. As an example, WooCommerce adds new pages to the wp_posts
database that help set up the website to work with it. In my opinion this is a mess, if you already have a WordPress website running, installing this theme/plugin will mess with your current page structures and whenever you want to uninstall it or deactivate it you will need to manually remove those pages created previously by the plugin. I once wanted to test an advanced WordPress theme that deleted all the current pages I had… that was the most annoying thing ever, since I already had written the content for the website and lost it (yes, I should have backed up but, who would expect a theme to delete and install pages without even a warning?).
A few weeks ago I posted a question in WordPress StackExchange but couldn’t really get the answer I was looking for, there was this solution to create fake posts but I wanted generate unlimited pages with simple code as possible and using friendly URLs like: http://example.com/?plugin_page=myfakepage (I could then easily use mod_rewrite
to make them look even better). Today I kept investigating and finally came with the solution.
Step by step guide
We will load the page at http://example.com/ but modify its title, content and select a blank theme template so it looks like a complete new page.
Custom page content
First of all we create a function that will overwrite the content:
function plugin_myown_content() { $return = ' <p>Fill in this form:</p> <form action="?" method="post"> <input type="text" name="foo" value="bar" /> <input type="submit" value="Connect" /> </form> '; return $return; }
Custom page title
Now we overwrite the title of the page with this function:
function plugin_myown_title() { return "On the fly foobar form"; }
Default page template
With this function we force WordPress to load the default page template of the current active theme:
function plugin_myown_template() { include(TEMPLATEPATH."/page.php"); exit; }
Hook actions and filters
Finally, we add a simple if
to check if the user is requesting the plugin’s fake page and run WordPress hooks to load the 3 functions mentioned before and force WordPress into displaying the virtual page we have just generated.
if ($_GET['plugin_page'] == "myfakepage") { add_filter('the_title','plugin_myown_title'); add_filter('the_content','plugin_myown_content'); add_action('template_redirect', 'plugin_myown_template'); }
The code is pretty basic, from here you can add your desired PHP code to make it do whatever you want. You can also add more hooks to customize the page even further. I hope you get the idea. This code has been tested with the latest version of WordPress (3.3.1).
18 comments
Edgar says:
This will not work if the the theme you are using does not have a page.php
David says:
Edgar, you can rename “page.php” to “index.php”, “single.php” or whatever other file your theme has and it will work.
Although page.php is an essential file of any WP theme, why would you develop a theme without the page.php?
Courier says:
Brutal Xavi! Hem vindrà de perles per un projectet que estic preparant!! Bona feina!
Makar says:
Hi,
I saw your post and thought maybe you can help me.
I’m trying to put logo’s on virual generated pages. I’ve tried to doe it with <?php if(is_page()). But ofcource thats not working beacuse there is only one page id, on which the other pages are generated. My virtual pages are generated by a forum plugin, so I have to work around it. Do you have any idea how i could work around the "one idea problem?"
thanks,
Makar
MadtownLems says:
Great start, but a couple major problems with this code:
– If your home is set to show latest posts, your ‘fake page’ will displayed over and over again.
– If you have any widgets that loop over posts, this replaces the titles of all of them with their own titles
Josh says:
Awlad says:
Hi David,
Could you please explain more details.Such as which part of code should put in which file???I am little bit cofused here.
Thanks
Brianoz says:
Xavi, I loved this well written article and your technique and am using it in a new large plugin. It seems ideal to include the active theme page.php for styling the site.
The bad news however, is that this doesn’t work with twentytwelve as the the_content filter doesn’t fire when I include page.php. One suggestion is that twentytwelve thinks there is no content.
Any idea how I could get this to work? I’m at my wits end having worn my fingers down to stumps with googling, and nobody seems to have a solution. I imagine other themes will be in the same position, but I’m not even sure how to kludge around twentytwelve’s issue.
Xavi Author says:
Hi Brianoz,
Have you tried including single.php or index.php instead of page.php? Also, there’s some good points and alternatives in the comments above.
Another option you could do is to include header and footer (as per Josh’s comment) including your content in the middle, that is not definitely the most reliable way but I guess as a last resort for problematic themes it should work.
Nugo says:
Hi Xavi,
I want to use your solution on a musicsite, and will have urls like this one mycompany.com/music/artist1/track1.mp3. I’m testing the url with a check of $_SERVER[‘REQUEST_URI’], but not sure how I should continue. Any ideas on how I can approach the challenge?
drmosko says:
hello, I use ur solution
and need to create on fly page with header 503, do u have any idea how to help me?
Brianoz says:
Xavi, While your suggestions didn’t work (some pages don’t call
the_post()
so no hook triggered, IIRC) I did get a working solution using a technique similar to yours in a stackexchange question here:There’s a link to a class that allows multiple specs of regexes to trigger virtual pages to call associated functions.
Thanks for your initial ideas; yours was the only post I could find anywhere doing near what I wanted, which was the base the virtual page on the existing theme. As far as I could tell at the time, your solution wouldn’t work after a WordPress upgrade (of course, I may be utterly wrong, apologies if I am).
article at: http://stackoverflow.com/questions/17960649/wordpress-plugin-generating-virtual-pages-and-using-theme-template
Elliot says:
This works a treat – Nice work and thanks for posting
Justin says:
Great solution! My only question is this. Will these pages stay within the database and then be indexed by Google’s crawl bot? My goal is to give a user options in a form like you have here and let the visitors create the pages for me based on their options.
Xavi Author says:
Hi Justin, As long as it’s got a unique URL that can be accessed from anywhere and no meta noindex it will be crawled and indexed.
Austin Hines says:
YES! This is just what I needed! Thank you so much!