title: Adding Mod Rewrite Rules Programmatically in WordPress Plugin
body: <p>The following sample plugin adds the custom mod rewrite rules to <code>.htaccess</code> when the user changes the permalink settings.</p>
  
  <pre><code>/* Plugin Name: Sample Mod Rewrite  */
  
  add_action('generate_rewrite_rules', array(new custom_mod_rewrite, "generate_rewrite_rules"));
  
  class custom_mod_rewrite {
      function __construct() {
          $this-&gt;wp_rewrite = &amp; $GLOBALS["wp_rewrite"];
      }
      function generate_rewrite_rules() {
  
          $non_wp_rules = array(
              'simple-redirect/?$plugin_name' =&gt; 'http://google.com',
              'one-more-redirect/?$plugin_name' =&gt; 'http://yahoo.com'
          );
  
          $this-&gt;wp_rewrite-&gt;non_wp_rules = $non_wp_rules + $this-&gt;wp_rewrite-&gt;non_wp_rules;
          add_filter('mod_rewrite_rules', array(&amp;$this, "mod_rewrite_rules"));
      }
      function mod_rewrite_rules($rules) {
          return preg_replace('#^(RewriteRule \^.*/)\?\$plugin_name .*(http://.*) \[QSA,L\]#mi', '$1 $2 [R=301,L]', $rules);
      }
  }
  </code></pre>
  
  <p>There are two problems I found with this. </p>
  
  <ol>
  <li>If it is set to the default permalink, it won't add the rules.</li>
  <li><s>More importantly, unless the user changes the permalink settings, the rules won't be added.</s> (can be solved with <code>$wp_rewrite-&gt;flush_rules()</code> performed at the plugin activation)</li>
  </ol>
  
  <p>For #2, I'm wondering if there is a good way to add the rules programmatically.</p>
  
  <blockquote>
    <p>IIS (common on Windows servers) does not support mod_rewrite.</p>
  </blockquote>
  
  <p>source: <a href="http://codex.wordpress.org/Using_Permalinks#Permalinks_without_mod_rewrite">http://codex.wordpress.org/Using_Permalinks#Permalinks_without_mod_rewrite</a></p>
  
  <p>It sounds like not all systems use <code>.htaccess</code>. So directly editing the <code>.htaccess</code> file may not be the best choice for a distributed plugin. I don't know. Probably I have to check if the server uses Apache and if so I need to check whether .htacess is writable and existing rules do not have the adding rules, then at last I can append the rules to it. Also when the user deactivate the plugin, the rules have to be erased. So it's kind of troublesome.</p>
  
  <p>If WordPress can handle it with a built-in API or something, I'd like to leave it to WordPress. But the above example was what I could have found so far. So I appreciate your information.</p>
  
  <p><strong>Update</strong></p>
  
  <p>As <em>pfefferle</em> suggested, I could use <code>$wp_rewrite-&gt;flush_rules()</code>. However, the problem #1 still persists; it won't take any effect when the default permalink settings is used. Any ideas?</p>
  
  <pre><code>/* Plugin Name: Sample Mod Rewrite  */
  
  $custom_mod_rewrite = new custom_mod_rewrite;
  register_activation_hook( __FILE__, array($custom_mod_rewrite, 'flush_rewrite_rules'));
  register_deactivation_hook( __FILE__, array($custom_mod_rewrite, 'flush_rewrite_rules'));
  add_action('generate_rewrite_rules', array($custom_mod_rewrite, "generate_rewrite_rules"));
  
  class custom_mod_rewrite {
      function __construct() {
          $this-&gt;wp_rewrite = &amp; $GLOBALS["wp_rewrite"];
      }
      function flush_rewrite_rules() {
          $this-&gt;wp_rewrite-&gt;flush_rules();
      }
      function generate_rewrite_rules() {
  
          $non_wp_rules = array(
              'simple-redirect/?$plugin_name' =&gt; 'http://google.com',
              'one-more-redirect/?$plugin_name' =&gt; 'http://yahoo.com'
          );
  
          $this-&gt;wp_rewrite-&gt;non_wp_rules = $non_wp_rules + $this-&gt;wp_rewrite-&gt;non_wp_rules;
          add_filter('mod_rewrite_rules', array(&amp;$this, "mod_rewrite_rules"));
      }
      function mod_rewrite_rules($rules) {
          return preg_replace('#^(RewriteRule \^.*/)\?\$plugin_name .*(http://.*) \[QSA,L\]#mi', '$1 $2 [R=301,L]', $rules);
      }
  }
  </code></pre>
  
  <p>Also, when deactivating the plugin, it doesn't change back to the previous rules. I just followed the codex example and just set it to flush the rules when deactivating the plugin. So there should be some code to delete the added rules. </p>
  
  <p>As a side note, according to <a href="http://codex.wordpress.org/Function_Reference/flush_rewrite_rules">the codex</a>,</p>
  
  <blockquote>
    <p>Flushing the rewrite rules is an expensive operation, ... ... you should flush rewrite rules on the activation hook of a plugin, or when you know that the rewrite rules need to be changed</p>
  </blockquote>
  
  <p><strong>Remaining Issues:</strong></p>
  
  <ol>
  <li>If it is set to the default permalink, it won't add the rules.</li>
  <li>When deactivating the plugin, it doesn't change back to the previous rules.</li>
  </ol>