如何使用mod_rewrite显示SEO友好的URL?

4

我本不是一名PHP开发者,但我被要求对一个现有的PHP网站进行一些SEO优化。

我注意到的第一件事是这些丑陋的URL,所以我想将它们重写为更具信息性的内容。以下是所有可能的模式:

/index.php?m=ModuleType&categoryID=id
/index.php?m=ModuleType&categoryID=id&productID=id
/index.php?page=PageType
/index.php?page=PageType&detail=yes

所以基本上我想要做的是将这些转换成类似以下这样的东西:
/ModuleType/Category
/ModuleType/Category/ProductName
/Page
/Page

我以前没有使用过mod_rewrite,任何建议或示例都会很好!

谢谢。

3个回答

1

mod_rewrite 更适合用于相反的操作:将 /ModuleType/Category/ProductName 的请求内部重写为 /index.php?m=ModuleType&categoryID=id&productID=id。在文档中使用新的 URL 是您的应用程序的工作。


编辑 这是一个示例函数,它可以将您的参数化URL转换为新的URL:

function url($url, $rules) {
    $url = parse_url($url);
    parse_str($url['query'], $url['query']);
    $argNames = array_keys($url['query']);
    foreach ($rules as $rule) {
        if ($rule[0] == $url['path'] && array_keys($rule[1]) == $argNames) {
            $newUrl = $rule[2];
            foreach ($rule[1] as $name => $pattern) {
                if (!preg_match('/'.addcslashes($pattern, '/').'/', $url['query'][$name], $match)) {
                    continue 2;
                }
                $newUrl = str_replace('<'.$name.'>', $match[0], $newUrl);
            }
            return $newUrl;
        }
    }
    return $url;
}

$rules = array(
    array(
        '/index.php',
        array('m'=>'.*', 'categoryID'=>'.*', 'productID'=>'.*'),
        '/<m>/<categoryID>/<productID>'
    )
);
echo '<a href="' . url('/index.php?m=ModuleType&categoryID=categoryID&productID=productID', $rules) . '">/ModuleType/Category/ProductName</a>';

那么我该怎么做呢?如何将参数化查询转换为更好的URL? - James
@James:你的网络应用程序应该可以做到这一点。通常情况下,你需要有一个映射来将一个表单映射到另一个表单。 - Gumbo
是的,但我不太确定如何做到这一点,你能提供一个例子吗? - James
@James:是从“美好变参量化”还是从“参数化变美好”的方向? - Gumbo
我需要使用mod-rewrite吗? - user3733831
显示剩余5条评论

1

我并不是mod_rewrite的专家,但这是我为Image Flair网站编写.htaccess文件的示例:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)/(.*)\.png$ imageFlair.php?mode=$1&userid=$2 [L]
RewriteRule ^(.*)\.png$ imageFlair.php?userid=$1 [L]
</IfModule>

这基本上是一个映射:

MODE/USERID.png -> imageFlair.php?mode=MODE&userid=USERID

USERID.png -> imageFlair.php?userid=USERID

你应该能够根据自己的需要进行调整,但可能会遇到一些问题:

  1. 如果您想在URL中使用“名称”而不是ID,则需要更改PHP以接受名称。
  2. 如果您想在Page中包含更多参数,除非您可以组合一个可以确定哪个是哪个的正则表达式,否则您可能会遇到/Page和/ModuleType冲突的问题。

根据您想要的URL列表,这应该可以工作,虽然我不会声称这是最好或唯一的方法 :-)

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)/(.*)/(.*)$ index.php?m=$1&categoryID=$2&productID=$3 [L]
RewriteRule ^(.*)/(.*)$ index.php?m=$1&categoryID=$2 [L]
RewriteRule ^(.*)$ index.php?Page=$1 [L]
</IfModule>

如建议的那样,您可能想用 [^/]+ 替换 .* 但是当我这样做时遇到了非匹配问题,而且没有时间进行故障排除,所以结果可能因人而异 :-)


请将 .* 替换为 [^/]+ 并在 URL 路径末尾标记 $ - Gumbo
嗨Steve,感谢提供的示例!我总是觉得学习起来更容易...请问重写规则末尾的L参数是什么意思? - James
它只是告诉 Apache 一旦匹配规则,就停止处理该请求。 - Steven Robbins
我加入了那个规则,但是我的所有JavaScript都出现了错误!把它拿掉后,它们就正常运行了。 - James
1
使用 [^/] 而不是 . 更加明确和高效,因为它避免了回溯。 - Gumbo
显示剩余4条评论

1

从您的帖子中并不完全清楚变量是什么。但是假设ModuleTypeid(x2)和Page都是变量,则以下带有反向引用的规则应该在.htaccess文件中起作用。

RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)$ /index.php?m=$1&categoryID=$2 [L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)$ /index.php?m=$1&categoryID=$2&productID=$3 [L]
RewriteRule ^([^/]+)$ /index.php?page=PageType [L]
RewriteRule ^([^/]+)/detail$ /index.php?page=PageType&detail=yes [L]

你之前写的那个不太通顺。所以你可以在结尾加上/detail

这些应该可以直接覆盖你现有的应用程序,而无需对应用程序进行任何修改。因为它们没有使用[R]进行重定向,所以对于你的用户来说是透明的。


嗨,丹,对于上次的事情我很抱歉,我从没想过要区分这两个!不过这确实是一个理想的解决方案。我会试一试的。 - James
嗨,我把你的规则输入到了 .htaccess 文件中,但它们似乎没有起作用?我需要重新启动什么吗?对不起,当涉及到 PHP 时,我有点新手。 - James
我已经更新了它,使得它适合直接粘贴到.htaccess文件中。 - Dan Carley
我认为你在每个规则的开头缺少了一个反斜杠,我加上了这个反斜杠,错误就不再出现了。然而,这些规则似乎没有生效。 - James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接