If you are wanting to know how to add your own custom content/rewrite rules to your WordPress .htaccess file without manually editing the .htaccess file, this information is for you.
Upon recently trying to figure out how to add contents to my WordPress generated .htaccess file, I was surprised at how hard it was to find information on this. Luckily though I came across WP htaccess Control plugin, which showed where and how to hook the necessary action/filter hooks to do what I was trying to do.
So here's a run down of what I found:
One helpful bit of knowledge is knowing where the .htaccess
file is created/generated from within WordPress. It all starts with the WP_Rewrite class, which is located in wp-includes/rewrite.php
file.
The main class methods of interest are mod_rewrite_rules()
(which is responsible for generating the .htaccess file rules), flush_rules()
(calls save_mod_rewrite_rules()), and the save_mod_rewrite_rules() (which writes the rules to the .htaccess file).
If you ever wondered where to grab what is going to be written to the .htaccess file, the mod_rewrite_rules filter hook is the one you're probably interested in.
This returns a string of the .htaccess generated rules, which allows for appending/pre-pending your own rules and/or modifying the string.
Here's an example of using this hook:
<?php /** * Get .htaccess contents before being written to file * * Uncomment the first two lines and to go Settings > Permalinks to see the output. */ function my_htaccess_contents( $rules ) { // echo '<pre>'. $rules .'</pre>'; // exit(); return $rules . "# My little addition!\n"; } add_filter('mod_rewrite_rules', 'my_htaccess_contents');
The output should be something like this:
RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] # My little addition!
That's an example of how we can append our own content to the end of the generated rewrite rules.
Ok, so perhaps you're wondering where the #BEGIN WordPress
and #END WordPress
lines are at....
Well, the answer is in the wp-admin/includes/misc.php
file's save_mod_rewrite_rules() function and it's call to insert_with_markers() (which saves the .htaccess file with the "markers").
If you are wanting to add .htaccess rules or additional directives when WordPress generates the .htaccess file, here's how to do it.
Here's two different ways you might want to add .htaccess file rules...
So say you want to add cache headers based on content, file access restrictions, or whatever else you can find to put in your .htaccess
file.
For this, we use the above example for hooking the mod_rewrite_rules filter hook.
Your filter function is passed the generated rules as a string and it MUST be returned.
Here you can choose to return it with your rules prepended or appended to the generated rules. Here's an example of that:
<?php function my_htaccess_contents( $rules ) { $my_content = <<<EOD \n # BEGIN My Added Content # Protect wpconfig.php <Files wp-config.php> Order Allow,Deny Deny from all </Files> # END My Added Content\n EOD; return $my_content . $rules; } add_filter('mod_rewrite_rules', 'my_htaccess_contents');
This will now make our .htaccess
contents look something like this:
# BEGIN My Added Content # Protect wpconfig.php <Files wp-config.php> Order Allow,Deny Deny from all </Files> # END My Added Content RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L]
Perhaps you need to add rewrite rules that don't pertain to WordPress' internal rewriting and possibly even point to a completely different URL.
WordPress can also add these rules to your .htaccess
file when it generates one!
The best way to add our non-WordPress rewrite rules (thanks Otto) is by using the add_rewrite_rule().
<?php function add_my_external_rules() { add_rewrite_rule('myrule', '/newlocation'); } add_action('init', 'add_my_external_rules');
Any rules that don't start with index.php will be added to the .htaccess
files as a normal RewriteRule when the rules are flushed.
Here's the example of what our .htaccess file will look like with the added rule..
# BEGIN WordPress <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteRule ^myrule /newlocation [QSA,L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule>
Ok, so I haven't told you how to make WordPress re-generate the .htaccess file with the updated rules/directives ...
There's a couple of ways to do this:
1. Make a "flush_rules" function.
admin_init
action hook so it'll only be called when any administrative page is loaded.2. Visit the Permalink Settings page.
.htaccess
file to reflect the changes. So this is probably the easiest way to regenerate the .htaccess
file once you've added your rewrite hooks as mentioned above.WordPress Multisite (aka. Network Site) differs from single instances and the fact that the .htaccess rules apply to the entire network, flushing the rules won't re-generate the .htaccess file.
I am currently unaware of how to add custom .htaccess
content/rules at this time since there doesn't appear to be any built-in WordPress functions for this in Multisite mode.