Apache 上 PHP 中的奇怪 URL 匹配行为

Strange URL match behaviour in PHP on Apache

TL;DR

如果我有一个 /campaign.php 文件 /campaign/some-url-stuff 匹配它而不是使用 .htaccess

中的重写规则

我刚刚为复活节活动制作了一个脚本并将其命名为 campaign.php 我将其设置为处理 GET 参数 name 所以示例 URL:https://localhost/campaign.php?name=Easter2021

然后我转到我的 .htaccess 文件(windows 上的 apache 2.4)并在其中创建了一行:

RewriteRule ^campaign/(.+)$ /campaign.php?name= [L]

使用 this debugger 验证使用以下 URL 调用它是正确的:https://localhost/campaign/Easter2021

然后我在我的脚本中添加了一些错误处理:

MCVE

<?php
$campaignName = filter_input(INPUT_GET,'name',FILTER_SANITIZE_STRING);
if ($campaignName == 'Easter2021') {
    echo "OK";
} else {
    header("content-type text/plain");
    echo "Invalid campaign Requested [$campaignName]";
    print_r($_GET);
}

所以如果我的文件和漂亮URL的根一样被调用,好像是被调用了,规则不匹配,这意味着我没有name 获取参数。 print_r($_GET); returns Array ( )

但是如果我重命名文件并将我的 .htaccess 更新为:RewriteRule ^campaign/(.+)$ /campaignHandler.php?name= [L]

然后https://localhost/campaign/sdfdsfsdf给出Array ( [name] => sdfdsfsdf )

问题 是:为什么? 以后我该怎么做才能避免这种情况? (必须有一些 php/apache 配置来解决这个问题)

在思考这个问题并练习一些 Google 之后,我偶然发现了 this question SO。
罪魁祸首是 Apache httpd's Multiview 功能,如果不存在具有要求名称的文件,它将查看服务器上存在的文件的基本名称,并提供其中一个。

Options -Multiviews 添加到 .htaccess 文件可解决问题。

更新

您可能无权覆盖 .htaccess 文件中的此设置。如果您确实有权访问 vhost 配置,请检查 <directory> Options 中是否没有 multiview