Let's say I create a customer support plugin that hijacks the /support part of the URL and redirects it to an MVC framework in my app folder of my plugin folder, like so:

RewriteRule ^support(.*)$ wp-content/plugins/csupport/app/$1 [L]

I know that I can do this in a blog's .htaccess right before the RewriteBase line, but not everyone has .htaccess turned on unless they add a custom permalink. I found a technique to force custom permalinks, but that's brute force and not recommended.

What is the recommended way for plugin developers to add a rewrite rule so that they can capture a subdirectory call like /support and redirect it to somewhere else?


Here's a solution. See comments at the end...

// I am a functions.php file of a plugin called "sample" -- implement me slightly differently for a theme.
// Note this code requires WP 3.0 or greater.
class SAMPLE {

public static function activatePlugin() {
  if (get_option('permalink_structure') == '') {
  // add your other plugin activation code here

public static function deactivatePlugin(){
  // add your other plugin deactivation code here

public static function drawAdminMenu(){
$s = <<<EOD
<div class="wrap">
  <div id="icon-options-general" class="icon32"><br></div>
  <h2>Sample Panel</h2>
  <!-- kludge to fix permalinks issue -- this ties into the plugin activation code -->
  <iframe style="position:absolute;top:-5000px" src="<?= admin_url() ?>options-permalink.php"></iframe>
  <p>Your options go here.</p>
</div><!-- .wrap -->
  echo $s;

public static function rewriteURL(){
  // this edits your .htaccess file and adds: 
  // RewriteRule ^support(.*)$ /wp-content/plugins/sample/app/$1 [QSA,L]

public static function updatePermalinks(){
global $wp_rewrite;
  // Note that the rest of this runs via the registration form via hidden IFRAME
  // in order to create the .htaccess file. It's a kludge -- but she works well!

} // end SAMPLE class

add_action('admin_menu', 'SAMPLE::drawAdminMenu');
  1. You should never run flush_rewrite_rules() all the time. Andrew Nacin, one of the core devs for WordPress, advises on more than one occasion that this must be done from a plugin or theme's activation and deactivation callbacks. (Themes don't have these callbacks, but there are examples on the web that kludge theme callbacks for activation/deactivation.) Andrew says it degrades performance, if otherwise. This is obvious because it could potentially rewrite the .htaccess file every time a page load occurs.

  2. I use static class methods instead of global functions in the namespace. It's less dangerous and more tidy.

  3. Note the sequence in the activatePlugin() -- that's important. You should rewrite the URL, flush the rules, and, if custom permalinks are not turned on, turn them on.

  4. Custom permalinks are crucial. Without them you don't get the .htaccess file and thus no rewrite rules.

  5. Note that we don't blindly brute-force custom permalinks on someone. We see if they have these enabled. If not, we turn them on and use a common kind of permalink often used with SEO.

  6. Note my updatePermalinks() function has a problem. It's something I detected in all versions of WordPress. I found that the .htaccess file was not being created unless one clicked to see the Permalinks options panel. I have no idea why WordPress has this bug, but it does. So, as you can see with the IFRAME below, I came up with a decent workaround. That IFRAME will ensure the .htaccess file gets created if it was not -- as long as that call to updatePermalinks() was done previously.

  7. The WordPress Codex seemed to indicate that I would have all kinds of problems with query parameters in my rewritten URL if I didn't implement add_query_vars(). However, I found that not to be the case at all. I was able to hijack /support and redirect it to an MVC framework inside my plugin, and then load that framework up with fancy URLs like /support/tickets/1, as well as use query parameters on the end like /support/tickets/1?q=open&s=sample+keywords.

  8. Note that:


...equates to:

RewriteRule ^support(.*)$ /wp-content/plugins/sample/app/$1 [QSA,L]

...in the .htaccess file, which is exactly what I needed.

As for why the docs are so confusing and misleading on the topic of RewriteRules, I have no idea.

EDIT1: Changed site_url() to admin_url() in the IFRAME call.

  • this works in certain cases, but isn't very portable since you rely on mod_rewrite being available and .htaccess being writable. also your rewrite rule assumes home url and site url are the same. perhaps consider a fallback of creating a page through which requests can be routed and give users the option of selecting which method to use.
    – Milo
    Mar 27 '12 at 3:00
  • You are right. It's not meant to be portable and must require .htaccess and mod_rewrite. That is, unless you can come up with a solution that works without that.
    – Volomike
    Mar 27 '12 at 3:09
  • @Milo can you explain why home url and site url might not be the same?
    – Volomike
    Mar 27 '12 at 3:10
  • WordPress can be installed in a different directory from where it's publicly served, so it's possible wp-content is one directory below that htaccess file. as for an alternate solution- don't use rewrites at all, create a page through which requests are routed, hook early in the request and check if that page is the requested page, and then load your plugin code. for an example, look at how most shopping cart plugins create their cart and checkout pages.
    – Milo
    Mar 27 '12 at 4:04
  • @Milo Good thing I interacted with you! I just learned the difference between site_url() and home_url(). I had several other parts of my code referencing site_url() instead of home_url(). In the code above, I also changed and used admin_url().
    – Volomike
    Mar 27 '12 at 7:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.