解决 WordPres 子目录的404错误

最近博客换了空间,还原数据库和文件后发现有些子目录访问不能访问,出现404错误。费劲周折终于解决了这个问题,把原理和过程写下来,希望能给遇到同样问题的朋友提供一个参考。

我把WordPress装在根目录,假设为public_html,然后再建子目录存放子站,最终的目录结构形如:

# WordPress root
public_html/
# Subdomain 1
public_html/subdir1/
# Subdomain 2
pubic_html/subdir2/

测试发现有些子目录能访问,有些不能;更离奇的是WordPress自带的目录wp-includes竟然都不能访问!而wp-content, wp-admin却正常!

首先怀疑htaccess的问题,删除后果然一切正常。于是逐条排除htaccess的规则,最终定位在WordPress的Permalinks规则上。我们先来分析一下:

# BEGIN WordPress
# 中文部分为我加的注释,请勿拷贝到你的htaccess中
<IfModule mod_rewrite.c>
    # 开启重写
    RewriteEngine On
    # 定位更目录
    RewriteBase /

    # 规则1: 如果URI(Uniform Resource Identifier,即Domain后面的部分)为/index.php
    # 那么立即跳出重写规则
    RewriteRule ^index\.php$ - [L]

    # 规则2: 如果URI为文件
    # 那么跳出重写规则(如果不为文件则往下匹配)
    RewriteCond %{REQUEST_FILENAME} !-f

    # 规则3: 如果URI为目录
    # 那么跳出重写规则(如果不为目录则往下匹配)
    RewriteCond %{REQUEST_FILENAME} !-d

    # 规则4: 如果上述条件都不符合
    # 那么将URI参数传到WordPress的index.php进行处理
    RewriteRule . /index.php [L]
</IfModule>
# END WordPress

我们看一下规则4的原理:如果前面的所有规则都不匹配,那么htaccess会将URI作为参数传递到WordPress 的index.php文件中。index.php收到这个参数后,会将这个参数作为Permalink处理,具体方法是在数据库中搜索这个参数对应的Post、Category、Page等,并将对应的页面显示出来;如果数据库中没有这条记录,那么显示404错误。这个过程就是将Permalinks转换成id的过程。

再整体看一下上面的所有规则,这里使用了两个机制处理我们的URI:先是htaccess处理,如果htaccess处理不了就交给WordPress处理。404问题就出在这里,htaccess非常不负责任地把一个目录交给WordPress作为Permalink处理。如果我们访问一个子目录,如subdir1,那么应该在规则3中就已经产生匹配,并且跳出并访问该目录。但是这里匹配失败了,导致这个URI最后传给了WordPress。

找到问题就可以对症下药了:我们只要添加一些规则,保证匹配这些子目录后跳出就行了。

参考Apache的Manual(http://httpd.apache.org/docs/current/mod/mod_rewrite.html)写了几条规则测试,均未果。只好求助于万能的Google,搜了下发现遇到同样问题的还真不少,光是WordPress官网就有好几个帖子,似乎官网也没有满意的答案,只知道可能是空间商限制了。最后在WordPress Answers 找到了答案([原文链接](Cannot access non-wordpress subdirectories as wordpress overrides them with a 404 error)):

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteCond %{REQUEST_URI} ^/subdirectoryname1/(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^/subdirectoryname2/(.*)$ [OR]
    RewriteRule ^.*$ - [L]
</IfModule>

把subdirecoryname改成你自己的子目录名称就可以了,你可以将这条规则放在WordPress Rewrite规则的前面,也可以整合进WordPress的重写规则中,方法可以参考本站的Rwrite规则(<注意最后一条规则没有[OR]):

# BEGIN WordPress
# ShuYZ.com rewrite rules
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

# If visit subdirectories
# Then jump out
    RewriteCond %{REQUEST_URI} ^/apps/(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^/wap/(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^/wp-admin/(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^/wp-content/(.*)$ [OR]
    RewriteCond %{REQUEST_URI} ^/wp-includes/(.*)$
    RewriteRule ^.*$ - [L]

# Else if visit home page
# Then jump out
    RewriteRule ^index\.php$ - [L]

# Else if visit folder or file
# Then jump out
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

# Else
# The URI is permalinks, transfer it to WordPress
    RewriteRule . /index\.php [L]
</IfModule>

这样就可以完美地排除WordPress子目录了,跟404错误ByeBye吧。具体效果见本站的子目录: http://shuyz.com/appshttp://shuyz.com/wap

需要注意的是,本方法只能解决普通目录的404错误问题,对htpasswd加密的子目录无效。加密子目录的404解决方法可参考:  解决htaccess加密的WordPress子目录404错误

关键字:WordPress, 404错误, htaccess

本文链接:树叶的BLOG >> 解决 WordPres 子目录的404错误

本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 Unported许可协议进行许可。

上一篇 : 稳定的老牌50G免费网盘 —— ADrive 下一篇 : 解决htaccess加密的WordPress子目录404错误