如何从id到name制作htaccess规则

Har*_*jan 7 php .htaccess mod-rewrite url-rewriting

我有一个独特的数据列表:

假设我有以下数据:

id    name
1     Jhon
2     Peter 
3     Mark
4     Scotty
5     Marry
Run Code Online (Sandbox Code Playgroud)

我制定了一个.htaccess规则id:

RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]
Run Code Online (Sandbox Code Playgroud)

我的网址是:

http://localhost/mate/admin/site/brandlisting/3
Run Code Online (Sandbox Code Playgroud)

这适用于id.

现在我需要一个.htaccess名称规则,所以我为它制定了一个规则:

RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L]
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L]

http://localhost/mate/admin/site/brandlisting/Mark
Run Code Online (Sandbox Code Playgroud)

当我使用上述URL时,我在控制台中面临以下错误:

"NetworkError:400 Bad Request - http:// localhost/mate/admin/site/brandlisting/Mark "

并在浏览器中显示:

错误400您的请求无效.

我目前的.htaccess文件

RewriteEngine on

RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$

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

Options +FollowSymLinks -MultiViews
RewriteEngine On

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]

#RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
#RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]

RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L] 
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L] 
Run Code Online (Sandbox Code Playgroud)

smc*_*nes 1

.htaccess规则依赖秩序。如果您预计使用大量路由,请保持 htaccess 规则简单,并使用几个已编写的路由框架之一将路由放入 PHP 中。

.htaccess以下是关于文件不起作用的原因的逐行解释:

RewriteEngine on
Run Code Online (Sandbox Code Playgroud)

这打开了 RewriteEngine。到目前为止没有问题。

RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$    
RewriteCond %{REQUEST_URI} !wordpress/
Run Code Online (Sandbox Code Playgroud)

唯一匹配的RewriteRule是 WordPress。这似乎有效,所以让我们忽略这组规则。

RewriteRule (.*) /wordpress/$1 [L]

Options +FollowSymLinks -MultiViews

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Run Code Online (Sandbox Code Playgroud)

仅当请求的文件名不是文件或目录时才匹配以下内容。

RewriteRule .* index.php/$0 [PT,L]
Run Code Online (Sandbox Code Playgroud)

将任意路径重写PATH为index.php/ PATH。如果匹配则停止处理(注意Las last)。这意味着下面的任何内容都不会被激活。

#RewriteRule brandlisting/(.*)/ site/brandlisting?id=$1 [L]
#RewriteRule brandlisting/(.*) site/brandlisting?id=$1 [L]

RewriteRule brandlisting/(.*)/ site/brandlisting?name=$1 [L] 
RewriteRule brandlisting/(.*) site/brandlisting?name=$1 [L] 
Run Code Online (Sandbox Code Playgroud)

假设它不匹配.*(也称为从不匹配),请检查其他模式的路径。另请注意,您已注释的两行和未注释的两行都匹配相同的模式。如果一个有效,另一个就无效。

--专业提示:正则表达式有一个简写,用于包含带有尾部斜杠和不带斜杠的规则:/?相当于带有一个斜杠或不带斜杠。另一种写法是/{0,1}.

怎么修

.htaccess重定向规则很痛苦。我的经验法则是让它们尽可能容易编写,这使得它们易于阅读和维护。这个怎么做?将重定向逻辑推送到您的 PHP 程序,而不是强迫 Apache 依赖它。

解决方案1

这里唯一的方法htaccess是确保您了解Apache 重写标志告诉您的服务器要做什么,并进行相应的调整。您可以通过以下两种方式之一执行此操作:

  1. 首先显示您更具体的规则。即,将/site/brandlisting?name=$1规则移至规则之前.*

  2. 为任何后续处理添加单独的重写条件。根据上面链接的 Apache2 文档:

[L] 标志导致 mod_rewrite 停止处理规则集。在大多数情况下,这意味着如果规则匹配,则不会处理更多规则。这对应于 Perl 中的最后一个命令,或 C 中的 break 命令。使用此标志来指示应立即应用当前规则,而不考虑进一步的规则。

这里的关键点是它位于每个规则集中。构建新的规则集将继续处理。

应该有效的示例(未经测试):

RewriteEngine on

RewriteCond %{HTTP_HOST} ^localhost/mate/admin$ [NC,OR]
RewriteCond %{HTTP_HOST} ^localhost/mate/admin$

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

Options +FollowSymLinks -MultiViews
RewriteEngine On

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]

#New Rule Set
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Note that /? is the same as writing two separate rules,
# one with a slash at the end, and one without.
RewriteRule brandlisting/(.*)/? site/brandlisting?name=$1 [L] 
Run Code Online (Sandbox Code Playgroud)

有一些很棒的预建路由器,例如SilexSlim。如果您不想使用它们,您仍然可以使用自己的内部逻辑来解析各个部分。根据我的经验,我从档案中提取的内容越多.htaccess,你就会越高兴。它最终使调试问题变得更加容易,并且更容易迭代更改而不会引入意想不到的后果。

解决方案2

您可以将 PHP 路由器与我上面提供的文件结合使用.htaccess,如下所示:

// Slim example
$app = new Slim\Slim();
$app->get('/brandlisting/:key', function ($key) {
    if (is_numeric($key)) {
        $id = $key;
        // call/run $id logic
    } else {
        $name = $key;
        // call/run $name logic
    }
});
// ...
$app->run();
Run Code Online (Sandbox Code Playgroud)

如果您这样做,您可以从中删除任何brandlisting逻辑.htaccess并将其放入您的index.php.

结论

如果可以的话,经验告诉我,最好不要将应用程序逻辑写入.htaccess规则。相反,让您的.htaccess规则变得简单并使用路由库。如果您想使用.htaccess,请确保您了解您正在使用的Apache 重写标志,并且 Apache 从上到下读取所有内容。例如,如果[L]使用该标志,Apache 将停止读取规则集中的所有其他规则。这意味着,您必须创建一个新的规则集,其中包含需要处理的其他规则,或者首先放置更具体的规则。请记住,如果这些规则有[L]标志,它们也将停止执行任何后续规则。