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)
.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 依赖它。
这里唯一的方法htaccess是确保您了解Apache 重写标志告诉您的服务器要做什么,并进行相应的调整。您可以通过以下两种方式之一执行此操作:
首先显示您更具体的规则。即,将/site/brandlisting?name=$1规则移至规则之前.*。
为任何后续处理添加单独的重写条件。根据上面链接的 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)
有一些很棒的预建路由器,例如Silex和Slim。如果您不想使用它们,您仍然可以使用自己的内部逻辑来解析各个部分。根据我的经验,我从档案中提取的内容越多.htaccess,你就会越高兴。它最终使调试问题变得更加容易,并且更容易迭代更改而不会引入意想不到的后果。
您可以将 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]标志,它们也将停止执行任何后续规则。