如何使用 htaccess 将 URL 中的下划线替换为破折号?

发布于 2025-01-09 18:08:34 字数 2808 浏览 1 评论 0原文

我的网址类似于 example.com/test-page/now_here,但我希望该网址类似于 example.com/test-page/now-here

我在我的 .htaccess 文件中尝试了以下操作:

RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]
RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/_]*)$       $1-$2 [R=301]

但它不起作用。当我转到 /test-page/now-here 时收到 404 错误

我做错了什么?

这是我的完整 .htaccess

Options -Indexes

<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L]
    RewriteCond %{HTTPS} !=on
    RewriteCond %{HTTP_USER_AGENT} ^(.+)$
    RewriteCond %{SERVER_NAME} ^example\.com$
    RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
    RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]
    RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/_]*)$       $1-$2 [R=301]
    Header add Strict-Transport-Security "max-age=300"
</IfModule>
<IfModule mod_headers.c>
    <If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
        Header always set Strict-Transport-Security "max-age=31536000"
    </If>
</IfModule>

更新

@MrWhite 解决方案确实有效,现在当我转到 url test-page/now_here 时,它​​会转到 test-page/now-here ,但是它不会进入我的测试页面控制器中的 php 方法,这里是完整的代码:

class TestPage_Controller extends App_Controller {
    function index() {
        $this->smarty->assign('currentPage', 'testpage');
        $this->smarty->assign('pageTitle', 'Test Page');
        $this->smarty->assign('description', "This is a test page.");
        $this->smarty->display(MDCHAT_THEME . '/page_meta.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_header.tpl');
        $this->smarty->display(MDCHAT_THEME . '/test_page.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_footer.tpl');
    }

    function now_here() {
        $this->smarty->assign('currentPage', 'testpage');
        $this->smarty->assign('pageTitle', 'Test Page');
        $this->smarty->assign('description', "This is a test page.");
        $this->smarty->display(MDCHAT_THEME . '/page_meta.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_header.tpl');
        $this->smarty->display(MDCHAT_THEME . '/here.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_footer.tpl');
    }
}

当我转到 test-page/now-here 时,我得到的只是一个空白的白色页面,即使我通过 php 打开 php 错误后也是如此。 .ini display_errors = on 和我的 php 代码:

error_reporting(E_ALL);
ini_set('display_errors', 1);

仍然只是一个白屏。

I have URL that looks like this example.com/test-page/now_here, but I want the URL to look like example.com/test-page/now-here.

I have tried the following in my .htaccess file:

RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]
RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/_]*)$       $1-$2 [R=301]

But it did not work. I get a 404 error when I goto /test-page/now-here

What am I doing wrong?

Here is my full .htaccess:

Options -Indexes

<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php/$1 [L]
    RewriteCond %{HTTPS} !=on
    RewriteCond %{HTTP_USER_AGENT} ^(.+)$
    RewriteCond %{SERVER_NAME} ^example\.com$
    RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
    RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]
    RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/_]*)$       $1-$2 [R=301]
    Header add Strict-Transport-Security "max-age=300"
</IfModule>
<IfModule mod_headers.c>
    <If "%{REQUEST_SCHEME} == 'https' || %{HTTP:X-Forwarded-Proto} == 'https'">
        Header always set Strict-Transport-Security "max-age=31536000"
    </If>
</IfModule>

UPDATE

@MrWhite solution did work, and now when I goto the url test-page/now_here it goes to test-page/now-here, however its not going to my php method in my test page controller, here is the full code:

class TestPage_Controller extends App_Controller {
    function index() {
        $this->smarty->assign('currentPage', 'testpage');
        $this->smarty->assign('pageTitle', 'Test Page');
        $this->smarty->assign('description', "This is a test page.");
        $this->smarty->display(MDCHAT_THEME . '/page_meta.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_header.tpl');
        $this->smarty->display(MDCHAT_THEME . '/test_page.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_footer.tpl');
    }

    function now_here() {
        $this->smarty->assign('currentPage', 'testpage');
        $this->smarty->assign('pageTitle', 'Test Page');
        $this->smarty->assign('description', "This is a test page.");
        $this->smarty->display(MDCHAT_THEME . '/page_meta.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_header.tpl');
        $this->smarty->display(MDCHAT_THEME . '/here.tpl');
        $this->smarty->display(MDCHAT_THEME . '/page_footer.tpl');
    }
}

All I get when I goto test-page/now-here I get a blank white page even after I turned on php errors via php.ini display_errors = on and in my php code:

error_reporting(E_ALL);
ini_set('display_errors', 1);

Still just a white screen.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淑女气质 2025-01-16 18:08:34
RewriteEngine 开启
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_USER_AGENT} ^(.+)$
RewriteCond %{SERVER_NAME} ^example\.com$
重写规则 .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule ^(/?测试页/.*/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]
RewriteRule ^(/?测试页/.*/[^/]*?)_([^/_]*)$ $1-$2 [R=301]

您的规则顺序错误,因此实际上不会针对给定 URL 处理指令。但该规则中的正则表达式也不匹配示例 URL,因此无论如何也不会执行任何操作。

您使用的正则表达式将匹配 /test-page/something/now_here,而不是您的示例中的 /test-page/now_here 。根据您的示例,test-page/ 之后的 .*/额外

您现有的(看起来像)HTTP 到 HTTPS 以及非 www 到 www 的规范重定向也位于错误的位置(它需要在重写到前端控制器之前进行,否则最终会重定向到 index .php),但它也无法规范化 http://www.example.com/ (HTTP + www) https: //example.com/(HTTPS +非 www)。正如所写,它仅规范化 http://example.com/ (HTTP + 非 www)。

请尝试以下操作:

RewriteEngine On

# 1.0 - Replace underscores with hyphens in last path segment
RewriteRule ^(test-page/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]

# 1.1 - Redirect to remove the final underscore
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+?)\.?$ [NC]    
RewriteRule ^(test-page/[^/]*?)_([^/_]*)$ https://www.%1/$1-$2 [R=301,L]

# 2 - non-www to www AND HTTP to HTTPS
RewriteCond %{HTTP_USER_AGENT} .
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+?)\.?$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]

# 3 - Rewrite to front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]

注意:首先使用 302(临时)重定向进行测试以避免潜在的缓存问题。

我还想问为什么您只重定向(规范化)来自传递+ve User-Agent 字符串的用户代理的请求。 (是的,它很可能是一个恶意机器人。)但是您仍然将此类请求传递给前端控制器而不是阻止它。 (?) 我在上面的规则中留下了这个条件,只是简化了它,以防您有一些特定的要求。

您可能不需要 包装器。有了这个 指令,并且 mod_rewrite 突然不可用,那么您的网站无疑会以一种不明显的方式中断,并且您可能会收到大量 404,这可能不是捡了一段时间。如果没有此 指令,则站点将因服务器错误日志中的详细错误而中断,这可能会触发警报/通知。有关详细信息,请参阅网站管理员 SE 上的以下问题:https:/ /webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_USER_AGENT} ^(.+)$
RewriteCond %{SERVER_NAME} ^example\.com$
RewriteRule .* https://www.%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]
RewriteRule       ^(/?test-page/.*/[^/]*?)_([^/_]*)$       $1-$2 [R=301]

Your rules are in the wrong order, so the directives won't actually be processed for the given URL. But the regex in that rule doesn't match the example URL either, so wouldn't do anything anyway.

The regex you are using would match /test-page/something/now_here, not /test-page/now_here as in your example. The .*/ after test-page/ is extra based on your example.

Your existing (what looks-like) HTTP to HTTPS and non-www to www canonical redirect is also in the wrong place (it needs to go before the rewrite to the front-controller, otherwise it will end up redirecting to index.php), but it would also fail to canonicalise http://www.example.com/ (HTTP + www) and https://example.com/ (HTTPS + non-www). As written, it only canonicalises http://example.com/ (HTTP + non-www).

Try the following instead:

RewriteEngine On

# 1.0 - Replace underscores with hyphens in last path segment
RewriteRule ^(test-page/[^/]*?)_([^/]*?_[^/]*)$ $1-$2 [N]

# 1.1 - Redirect to remove the final underscore
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+?)\.?$ [NC]    
RewriteRule ^(test-page/[^/]*?)_([^/_]*)$ https://www.%1/$1-$2 [R=301,L]

# 2 - non-www to www AND HTTP to HTTPS
RewriteCond %{HTTP_USER_AGENT} .
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+?)\.?$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]

# 3 - Rewrite to front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]

NB: Test with a 302 (temporary) redirect first to avoid potential caching issues.

I would also question why you are only redirecting (canonicalising) requests from user-agents that pass a +ve User-Agent string. (Yes, it's quite possibly a malicious bot.) Yet you are still passing such requests to your front-controller and not blocking it. (?) I've left this condition in the above rule, just simplified it, in case you have some specific requirements.

You probably do not want the <IfModule mod_rewrite.c> wrapper. With this <IfModule> directive in place and mod_rewrite was suddenly not available then your site will no doubt break in a non-obvious way and you'll likely get a ton of 404s, which may not be picked up for a while. Without this <IfModule> directive then the site will break with a detailed error in the server's error log which should potentially trigger an alert/notification. See the following question on Webmasters SE for more info on this: https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文