惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 【当耐特】
A
About on SuperTechFans
Last Week in AI
Last Week in AI
雷峰网
雷峰网
IT之家
IT之家
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
博客园 - 叶小钗
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Docker
Engineering at Meta
Engineering at Meta
B
Blog RSS Feed
The Cloudflare Blog
大猫的无限游戏
大猫的无限游戏
阮一峰的网络日志
阮一峰的网络日志
S
SegmentFault 最新的问题
Recent Announcements
Recent Announcements

Comments for Jeremy Carlson

Pay attention. – Jeremy Carlson Can I use type in an image? – Jeremy Carlson Extract Source Images from a PDF in Photoshop – Jeremy Carlson
Excluding a directory from WordPress – Jeremy Carlson
Jeremy · 2017-02-04 · via Comments for Jeremy Carlson

I’m working on a site, and we have been storing archive copies of our newsletter on our site like this:

http://example.com/newsletter/2015-05/

The site itself has been a homegrown PHP solution which I’m finally, after years, converting to WordPress. One challenge is this folder structure. I don’t really want to mess with it. But I need http://example.com to run with WordPress. So I need to exclude the newsletter directory (folder, whatever).

I looked around and found a great tip on excluding a directory which shows just how to write the proper code into my .htaccess file, like this:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !^/(mydir|mydir/.*)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

The salient line that’s added is saying the REQUEST_URI must NOT be either ‘mydir’ or ‘mydir/whatever’. It’s great, works a treat.

But there’s one small problem.

If you change your permalinks, your rewrite rules are flushed, and the .htaccess file is overwritten. Now, you could just make sure your .htaccess file is not writable, but where’s the fun in that? Instead I want to tap into WordPress’s WP_Rewrite API and make sure that, should we change the file, this rule will be preserved.

Luckily the API has lots of hooks so we can manipulate things. I initially looked using the add_rewrite_rule function to add to the rewrite_rules array—since WordPress at one point has an array of all the rewrite rules that seemed handy. But then I noticed that the action to hook into that only seems to be working for rewrite RULES, not rewrite CONDITIONS.

Someone had already asked if WordPress had a function to generate a rewrite condition on StackExchange. The answer given was very helpful, leading me to use the mod_rewrite_rules hook to mess with the entire string of content just before it gets written to .htaccess.

First I need to define my new rule, like this:

// Create our condition.
$exclude_newsletter_cond = PHP_EOL . 'RewriteCond %{REQUEST_URI} !^/(newsletter/.*)$';

Then I’m going to insert this condition just after the line with RewriteBase—that’s a unique point that comes somewhere in the midst of the rules. This means the condition will get inserted BEFORE the first RewriteRule. But it works just fine. (YMMV)

I’m going to do a preg_replace to search for ‘RewriteBase.+’ and replace it that with itself, plus the string I created above. My search looks like this—remember you need the forward slashes in your search string for preg_replace:

$search = '/RewriteBase.+/';

And then we just replace it. You can see this in the full code example below.

/**
* We need to parse the rewrite rules string, and insert something
* INSIDE it. If this were a rewrite RULE, then we could insert it
* into the array that gets prepped before getting converted into a
* string. If you want to do that, may want to check out the Codex:
* https://codex.wordpress.org/Class_Reference/WP_Rewrite
* (Note: this would be a different hook , too)
*
* In our case, since we are creating a CONDITION, we need to muscle
* our way into the string.
*/
function my_custom_htaccess( $rules ){

// Create our condition.
$exclude_newsletter_cond = PHP_EOL . 'RewriteCond %{REQUEST_URI} !^/(newsletter/.*)$';

// Look for a place to insert it.
// We are going to put this just after the RewriteBase line.
// This is not in the same place as all the other RewriteCond statements,
// But it seems to work.
$search = '/RewriteBase.+/';

// Replace w/ found string, plus condition
$replace = '$0' . $exclude_newsletter_cond;

// Rock and roll.
$rules = preg_replace($search, $replace, $rules);

return $rules;
}
add_filter('mod_rewrite_rules', 'my_custom_htaccess');

This produces the following set of WordPress rules:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/(newsletter/.*)$
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

So yes, the RewriteCond does come before the first RewriteRule, but it worked locally. I’ll update this post if I find other issues.

If you found this, and it was helpful, let me know!