【问题标题】:How to write RewriteRules for .htaccess?如何为 .htaccess 编写 RewriteRules?
【发布时间】:2019-05-17 04:41:11
【问题描述】:

我有一个名为 otp.php 的 PHP 文件。

当 URL 栏中的 URL 为

http://localhost/college/otp/MTA=/teacher

应该被视为

http://localhost/college/otp.php?user=MTA=&role=teacher

为此,我在http://localhost/college/中创建了.htaccess文件:

RewriteEngine On    # Turn on the rewriting engine
RewriteRule    ^otp/?$    otp.php    [NC,L]
RewriteRule    ^otp/[A-Za-z-]+/([A-Za-z0-9-]+)/?$    otp.php?user=$1&role=$2    [NC,L]

但是,otp.php 文件说:

注意:未定义索引:角色在 C:\wamp\www\college\otp.php 上线 11

注意:未定义索引:用户在 C:\wamp\www\college\otp.php 上线 11

更新

当网址栏中的网址为

http://localhost/college/otp/MTA/teacher

应该被视为

http://localhost/college/otp.php?user=MTA&role=teacher

我该如何解决这个问题?

【问题讨论】:

  • 我认为以下问题应该对您有所帮助。 stackoverflow.com/questions/7876868/php-get-and-undefined-index
  • 您链接的问题与我无关,因为我在代码中使用isset,主要问题在.htaccess 文件中。 @Abhineet
  • [A-Za-z-]+ 与您在示例中显示的= 不匹配。因此该规则不会被应用。
  • 那怎么用呢?
  • 对您问题的最后一次更新 表明,即使您直接请求http://localhost/college/otp.php?user=MTA&role=teacher,您仍然会从PHP 获得这些“未定义索引”通知?你能证实这一点吗? (因为这会完全改变你问题的重点。)

标签: regex apache .htaccess mod-rewrite url-rewriting


【解决方案1】:

URL: /college/otp/MTA=/teacher
Target: /college/otp.php?user=MTA=&role=teacher
.htaccess: /college/.htaccess

RewriteRule    ^otp/[A-Za-z-]+/([A-Za-z0-9-]+)/?$    otp.php?user=$1&role=$2    [NC,L]

您的RewriteRule 模式 需要稍微修改以匹配您的示例 URL,因为它目前在 MTA= 中的 = 上会失败。 (尽管我刚刚注意到您的问题的“更新”没有在 URL 中显示 =?)此模式还需要捕获才能选择 $1起来吧。

所以,上面的指令应该是这样的:

 RewriteRule ^otp/([A-Za-z-]+=)/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2    [NC,L]

这假设 = always 出现在路径段的末尾,就像在您的初始示例中一样(如果它可以出现在任何地方,请将其包含在字符类中 - 尽管会有点混乱)。 NC 标志可能是不必要的,除非您还需要允许 otp 的混合大小写版本(不建议)。您已经允许在您的正则表达式中混合大小写。

UPDATE#1: 似乎第二个路径段是 base64 编码的字符串/整数。为此,您需要在正则表达式中包含数字,并且可能有 0、1 或 2 个尾随 = 字符。也不需要匹配连字符。例如:

 RewriteRule ^otp/([A-Za-z0-9]+={0,2})/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2    [NC,L]

但是,您似乎遇到的另一个问题(以及您实际“看到”的问题)是与 MultiViews(mod_negotiation 的一部分)的冲突。这需要禁用上述 mod_rewrite 指令才能工作(实际上,做任何事情)。如果您没有在 .htaccess 中启用此功能,请在您的 .htaccess 文件顶部添加以下内容来禁用它:

Options -MultiViews

如果启用了 MultiViews,那么当您请求 otp(其中存在具有相同 basename 的文件,它也会返回适当的 mime 类型)时,mod_negotiation 会为 otp.php 发出一个内部子请求。这里的问题是,这发生在 mod_rewrite 之前,所以 otp.php 最终被调用而没有任何 URL 参数。


旁白:

您的代码不应生成这些“未定义索引”通知。由于这本质上是“用户提供的数据”,因此您应该在脚本中检查它。例如:

$role = isset($_GET['role']) ? $_GET['role'] : null;
RewriteEngine On    # Turn on the rewriting engine

请注意,Apache 不支持行尾 cmets,因此您应该从第一行删除 # Turn on the rewriting engine 文本。 (行尾 cmets 可能看起来“工作”,然而,这只是与 Apache 指令的一般工作方式巧合,其他时候它们会导致 500 内部服务器错误。)


更新#2:

如果网址栏有http://localhost/college/otp.php?user=MTA=&role=teacher,可以改成http://localhost/college/otp/MTA/teacher吗?

是的,这可以做到。虽然我认为MTA= 应该出现在这两个地方? (源中有MTA=,目标中有MTA,这可能会破坏base64编码?)我假设您已经在内部链接到正确的URL,这只是为了使杂散请求(搜索引擎,反向链接)受益等?)

您可以在上述重写之前实现外部重定向,注意不要重定向重写的 URL 并触发重定向循环。例如:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^user=([A-Za-z0-9]+={0,2})&role=([A-Za-z0-9-]+)
RewriteRule ^(otp)\.php$ /college/$1/%1/%2 [QSD,R=302,L]

这基本上是 内部重写(稍后出现在 .htaccess 文件中)的逆过程。检查REDIRECT_STATUS 环境变量的条件确保它只触发直接请求而不是重写请求。

请注意,由于这是一个外部重定向,您需要在 substitution 参数中包含一个相对于根的 URL 路径。 IE。包括/college 子目录。 (或者,您可以使用相对 substitution 并设置 RewriteBase - 尽管只有当您有多个这些指令时才会这样做。)

$1 是对RewriteRule 的反向引用模式(即总是otp)和%1%2 是对前面CondPattern 的反向引用>,即。 userrole URL 参数的值。

QSD 标志 (Apache 2.4+) 会丢弃请求中的原始查询字符串。

【讨论】:

  • 当我尝试时:Options -MultiViews RewriteEngine On RewriteRule ^otp/?$ otp.php [NC,L] RewriteRule ^otp/([A-Za-z-]+=)/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2 [NC,L]404 Not Found。 & 当RewriteEngine On RewriteRule ^otp/?$ otp.php [NC,L] RewriteRule ^otp/([A-Za-z-]+=)/([A-Za-z0-9-]+)/?$ otp.php?user=$1&role=$2 [NC,L]同样的问题
  • 禁用 MultiViews 后,404 响应意味着 RewriteRule 不匹配。你要什么网址?这个.htaccess 文件中还有其他指令吗?还有其他.htaccess 文件吗?当您对第二个规则块说“相同的问题”时,您是说它也返回 404,并删除了 Options -MultiViews 指令?
  • 如果您编码为 base64,那么末尾可能有 0、1 或 2 =。您还需要匹配当前从您的正则表达式中省略的数字。因此,您将需要类似 ([A-Za-z0-9]+={0,2}) 的东西。我会更新我的答案。
  • 我已经更新了关于你关于反向操作的最后一部分的答案...从http://localhost/college/otp.php?user=MTA=&role=teacher重定向。
  • 啊,是的,您需要在 substitution 字符串中明确包含 /college 子目录。 IE。 /college/$1/%1/%2(相对于/$1/%1/%2)。我已经更新了我的答案。
【解决方案2】:

This tool 可能会帮助您为 RewriteRules 编写正确的表达式。也许,这个表达式会给你一个想法,问题可能出在哪里:

(.*otp)\/([A-Za-z0-9-]+=)\/([A-Za-z0-9-]+)

正则表达式描述图

link 可帮助您可视化 RewriteRule 的表达式:

然后,您可以编写一个 RewriteRule,可能类似于:

<IfModule mod_rewrite.c>
    RewriteEngine On    # Turn on the rewriting engine
    RewriteCond %{HTTP_HOST} localhost  [NC]
    RewriteRule    (.*otp)\/([A-Za-z0-9-]+=)\/([A-Za-z0-9-]+)  $1.php?user=$2&role=$3  [NC,L]
</IfModule>

您可能希望在每次修改 .htaccess 文件时清除浏览器历史记录。

【讨论】:

  • 我试过&lt;IfModule mod_rewrite.c&gt; RewriteEngine On # Turn on the rewriting engine RewriteCond %{HTTP_HOST} localhost [NC] RewriteRule (.*otp)\/([A-Za-z0-9-]+=)\/([A-Za-z0-9-]+) $1.php?user=$2&amp;role=$3 [NC,L] &lt;/IfModule&gt; 没有&lt;IfModule&gt;&lt;/IfModule&gt;,但也有同样的通知(也清除了浏览器历史记录)。 see image
  • 代码:- echo $role = $_GET['role'];,错误:- 注意:未定义索引:第 11 行 C:\wamp\www\college\otp.php 中的角色我>。虽然 role 是在 url 栏中定义的:http://localhost/jainvidhya/otp/MTA=/teacher 即:localhost/college/otp.php?user=MTA=&role=teacher
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
  • 2014-04-09
  • 2015-06-03
  • 1970-01-01
  • 1970-01-01
  • 2022-09-22
相关资源
最近更新 更多