mod_rewrite别名子目录

时间:2011-07-21 14:33:59

标签: mod-rewrite

我一如既往地在与mod_rewrite斗争。我们有许多通过WordPress多站点运行的客户端门户,所有门户都通过子目录portal访问。

例如:http://www.mydomain.com/portal/clientA/

我希望只需输入http://www.mydomain.com/clientA/就可以到达那里,它会将我重定向到http://www.mydomain.com/portal/clientA/

这是我到目前为止所做的,并且它没有产生任何重写,我可以告诉:

RewriteCond %{REQUEST_URI} /portal/
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [S=1]

RewriteRule /clientA(/?) /portal/clientA/

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

第二部分我无法触及,因为WordPress需要它。我的模式也试图预测某人没有进入尾随斜线,因此(/?)

编辑:我还应该注意,我不想创建更通用的规则 - 我很乐意为每个新客户端添加重写规则并增加{{1}每次都是数字。

编辑(8月11日),所以经过一点点推销后,这就是我的.htaccess所在:

S=x

毋庸置疑,它不起作用。但是,第一部分工作,如果我删除整个WordPress部分。我需要它们同时工作。什么是导致第一部分失败的WordPress片?我想这是RewriteBase和最后一条规则的组合,它将其他任何东西别名给/index.php,坦率地说这有点令人失望。事实上,我并不真正理解该规则在多站点环境中是如何工作的,但似乎也是如此。

最终解决方案 感谢LazyOne的正确答案!对于其他人的参考,我使用的最终解决方案是:

RewriteEngine On
RewriteRule ^clientA(/?) /portal/clientA/ [R]

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

# END WordPress

2 个答案:

答案 0 :(得分:2)

这很简单:

RewriteCond %{REQUEST_URI} !^/portal/
RewriteRule (.*) /portal/$1 [L]

它会将所有请求重写(内部重定向)到/portal/文件夹(例如/clientA/something =&gt; /portal/clientA/something)。

如果您只需要为某些客户端执行此操作(或者更好的说,只有特定文件夹是客户端,同时仍然保留一些常规/常用文件夹),您可以为每个客户端使用此规则:

RewriteRule ^clientA(.*) /portal/clientA$1 [L]

所以.htaccess看起来像这样:

RewriteRule ^clientA(.*) /portal/clientA$1 [L]
RewriteRule ^clientB(.*) /portal/clientB$1 [L]

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

答案 1 :(得分:0)

我发布了部分内容作为评论,但认为对于那些在这里作为答案的人来说可能会更清楚。对OPs来说,他找到了一种使用[R](重定向)行来实现此目的的方法,但这消除了您创建的子目录URL结构,这在大多数URL重写中更为可取。所以,之前发布的答案是正确的,我不是在争论,但根据您的实现,您可能仍然会收到WordPress 404错误。这是我的情况的解决方案,我认为可能更常见。

就我而言,我需要一个像这样的URL结构:

http://mysite.com/p/profile_name/

每个注册的用户都可以动态创建他/她自己的个人资料,除了对内容的一些修改外,大多数情况下根目录下的所有WordPress内容都将被显示。基本上,我需要这个:

http://mysite.com/p/profile_name/(.*)

要改写为:

http://mysite.com/$1

这是在正确处理该规则的另一个答案中发布的.htaccess代码:

RewriteRule ^p/([-a-zA-Z0-9_]+)(/.*) $2 [L]

问题在于,WordPress并不关心你在理解$ 2是什么方面的重写,因为WordPress使用$ _SERVER ['REQUEST_URI'],无论你重写什么,它总是在用户的浏览器窗口中是什么。 OP通过使用[R]选项找到了解决此问题的方法,但这会导致您丢失URL:

RewriteRule ^p/([-a-zA-Z0-9_]+)(/.*) $2 [R,L]

<强>重定向

http://mysite.com/p/profile/(.*)

要:

http://mysite.com/$1

但是,用户以这种方式丢失了他的唯一网址。最好你可以添加一个查询字符串来至少保留数据,但是你会失去漂亮网址的开头点。

我确实想出了一个解决方案;然而,它涉及黑客攻击WordPress包含文件:(如果有人有更好的方法,请更新。我们走了:

<强>解

我将.htaccess文件设置为等于:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
#My addition:
RewriteRule ^p/([-a-zA-Z0-9_]+)(/.*) $2 [L]

RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

然后,我知道WordPress使用了REQUEST_URI变量,因此我进行了递归搜索,并在/wp-includes/class-wp.php(第147行v3.4.2)中找到了这行代码:

$req_uri = $_SERVER['REQUEST_URI'];

我把它更改为:

$req_uri = preg_replace(@'/^\/?p\/([-a-zA-Z0-9_]+)\//', '', $_SERVER['REQUEST_URI']);

这基本上只是通过过滤URI开头的配置文件来欺骗WordPress。

最后,我还需要一个网站内链接的解决方案。为此,我添加了这个过滤器:

注意:其中一些正则表达可能有点疯狂;我过滤掉了特定于网站的内容,因此请将其用作概念,而不是复制/粘贴。

function mysite_wp_make_link_relative( $link ) {
    $sBaseUrl = (preg_match('/^\/(p\/[-a-zA-Z0-9_]+\/)(.*)/', $_SERVER['REQUEST_URI'], $matches)) ? $matches[1] : '';
    return preg_replace( '|https?://[^/]+/(.*)|i', '/' . $sBaseUrl . '$1', $link );
}
function rw_relative_urls() {
    $filters = array(
        'page_link', // Page link
        'home_url',
        'site_url',
        'get_site_url',
        'home_link',
    );
    foreach ( $filters as $filter ) {
        add_filter( $filter, 'mysite_wp_make_link_relative' );
    }
}

其中一些过滤器可能不相关;我很确定page_link和home_url是唯一重要的。无论如何,您需要该代码才能使内部链接正常工作。

我希望有帮助,如果有人有任何评论建议,我会非常感谢。