【问题标题】:mod_rewrite query strings returning 404mod_rewrite 查询字符串返回 404
【发布时间】:2017-01-04 05:42:19
【问题描述】:

我有一个这样的自定义 URL:

website.com/show/?id=9999&n=page-name 

我正在尝试提出一个重写规则将其转换为:

website.com/show/9999/page-name/

请注意,这是一个 WordPress 网站,/show/ 是 WP 页面名称。

这是我在 .htaccess 中使用的规则:

<IfModule mod_rewrite.c>
    Options -MultiViews
    RewriteEngine On
    RewriteBase /
    RewriteRule ^show/(.*)$ /show/?id=$1 [R=301,NC,QSA]
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
</IfModule>

这是有效的;它将website.com/show/?id=9999 重写为website.com/show/9999/

然后我修改了第二个查询字符串的规则:

RewriteRule ^show/(.*)/(.*)$ /show/?id=$1&n=$2 [R=301,NC,QSA]

但是现在website.com/show/9999/page-name/ 返回一个 404 错误。如果我去:website.com/show/9999/?n=page-name.

我做错了什么?

更新

404 问题is now solved

但是,现在我需要重定向旧的查询字符串 URL:

website.com/show/?id=9999&n=page-name 

到新的 SEO 友好 URL:

website.com/show/9999/page-name

如何设置重定向?

【问题讨论】:

    标签: php wordpress .htaccess mod-rewrite url-rewriting


    【解决方案1】:

    试试这个:

    Options +FollowSymLinks
    
    <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteBase /
    
        RewriteRule ^show/(\d+)/?([^/]*)/?$ /show/?id=$1&n=$2 [L,NC,QSA]
    
        # Wordpress defaults:
        RewriteRule ^index\.php$ - [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.php [L]
    </IfModule>
    ## Results
    # show/9999            => show/?id=9999&n=
    # show/9999/           => show/?id=9999&n=
    # show/9999/page-name  => show/?id=9999&n=page-name
    # show/9999/page-name/ => show/?id=9999&n=page-name
    

    如您所见,当page-name 不可用时,将有一个空的n 查询字符串参数。在您的 PHP 脚本中,不要使用 isset() 检查参数是否存在,而是尝试使用 empty()

    最后一个音符;上述规则不会重定向请求,它会在后台映射请求,从而使 URL 保持干净。如果您需要重定向,只需添加 R 标志。

    404

    即使您删除了自定义重写规则,您也会从 WordPress 获得 404。这是因为,正如您所说,重写目标 (/show) 是一个 WordPress 页面,并最终映射到 index.php 文件。然后,WordPress 检查它的数据库,看看它是否可以找到具有该路径的页面,如果不能,则抛出 404。显然,后者是你的情况。

    更新

    关于your recent update;要将旧 URL 重定向到新 URL,您需要一些重写规则,如下所示:

    Options +FollowSymLinks
    
    <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteBase /
    
        RewriteCond %{QUERY_STRING} ^id=(\d+)(&n=)?(.*)$
        RewriteRule ^show/?$ /show/%1/%3 [R=301,QSD,L]
    
        # Wordpress default rules:
        # ...
    </IfModule>
    ## Results
    # show?id=9999              => show/9999
    # show?id=9999&n=page-name  => show/9999/page-name
    # show/?id=9999&n=page-name => show/9999/page-name
    

    在您 100% 确定一切正常之前不要使用[R=301],因为它会被浏览器积极缓存。

    【讨论】:

    • 这仍然会为 website.com/show/9999/page-name 返回 404 错误。但是我可以从website.com/show/?id=9999&amp;n=page-name 访问该页面
    • 我敢肯定,即使您删除了 URL 重写规则,它仍然会返回 404 错误。因此,404 与重写过程无关。那是因为您依赖 WordPress 页面来实现重写目标。 WP 检查其数据库以查看页面是否存在并抛出 404,因为它不存在。如果可能的话,您可以将 PHP 文件放在那里并完全避免使用 WP。
    • 但是/show/9999/ 也不是现有页面,就像/show/9999/page-name/ 一样。那么为什么前者有效而不是后者呢?如果 /show/9999/page-name 重新映射到 /show/?id=9999&amp;n=page-name 并且我可以验证 URL 是否可访问,那么为什么它不起作用?
    • 我尝试创建一个show 目录并将index.php 文件放入其中,但访问/show/9999/page-name 时仍然得到404
    • 我将该重写规则放入 htaccess 中,但它引发了 500 内部服务器错误。我想出了一个有效的方法,请参阅我的答案。非常感谢您的帮助!
    【解决方案2】:

    我想我想通了……差不多。

    @sepehr 是正确的,WordPress 正在检查,没有找到页面,并抛出 404。所以我需要使用 WordPress 自己的重写引擎来定义重写规则,以便它识别我在做什么。

    所以我将此添加到我的 WordPress 主题的 functions.php 文件中:

    add_action( 'init', 'init_custom_rewrite' );
    
    function init_custom_rewrite() {
        add_rewrite_rule( 
            '^show/([^/]*)/([^/]*)/?',        
            'index.php?page_id=2382&id=$matches[1]&n=$matches[2]',        
            'top' 
        );
    }
    
    add_filter('query_vars', 'my_query_vars', 10, 1);
    
    function my_query_vars($vars) {
        $vars[] = 'id';
        $vars[] = 'n';
        return $vars;
    }
    

    现在 URL website.com/show/9999/page-name 可以正常工作,不会引发 404。

    但是,现在我需要将旧的查询字符串 URL 重定向到这个新的。见我的updated question

    更新

    以下是将旧查询字符串 URL 重定向到新的 SEO 友好 URL 的重写规则:

    RewriteCond %{QUERY_STRING} ^id=([^/]*)&n=([^/]*)$ 
    RewriteRule ^show/?$ /show\/%1\/%2\/? [R=301,L]
    

    【讨论】:

    • 太好了,干得好!我将更新我的答案以提供一个新规则集,将旧 URL 重写为新 URL。
    • 干得好。只是一些笔记;与查询字符串匹配时,您不需要那些 [^/] 组,因为它永远不会包含一个。此外,RewriteRulesubstitution 参数不需要转义 / 字符。
    【解决方案3】:

    请在您的 .htaccess 中检查以下规则。

    RewriteRule ^show/(.+)/(.+)$ show/?id=$1&n=$2 [L,QSA]
    

    【讨论】:

    • 这仍然会为website.com/show/9999/page-name/ 返回 404 错误。它还破坏了我的 PHP 脚本 $_GET[id],所以 website.com/show/9999/ 甚至不起作用。
    猜你喜欢
    • 1970-01-01
    • 2014-07-27
    • 1970-01-01
    • 2011-03-11
    • 1970-01-01
    • 1970-01-01
    • 2012-02-05
    • 2018-05-11
    • 2016-03-26
    相关资源
    最近更新 更多