路由文件
这是由于您在php: you set the routing file to be index.php 的命令中设置选项的方式...
php -S localhost:8888 index.php
^^^^^^^^^
...这意味着每个请求都将首先通过该文件,然后决定做什么。例如,假设我们的index.php文件包含以下内容:
if (rand(1,100) % 2) {
echo "Not a multiple of 2\n";
return true;
} else {
echo "Multiple of 2\n";
return false;
}
注意:return true;技术上不需要,但为了清楚起见,我已将其包括在内
这里发生的是发出请求并运行路由文件。如果路由文件返回false(即是2 的倍数),则请求将通过请求的文件。如果代码返回true,则执行停止并且不访问请求的文件。
在您的情况下,请求的文件是index.php(同一个文件),因此,使用上面的代码,您将始终得到如下输出:
Not a multiple of 2
// OR
Multiple of 2
Multiple of 2
// OR
Multiple of 2
Not a multiple of 2
使用您的代码/设置分解 http 请求
所以,看看你的实际代码......
session_start();
if (!empty($_POST['token'])) {
var_dump($_POST['token'], $_SESSION['token']);
exit;
}
$_SESSION['token'] = rand();
echo '<form ...>...</form';
这里会发生什么?
- 您提出请求
index.php*
- 服务器访问路由文件
index.php来决定做什么
- 路由文件输出的数据有效地表明
true
- 返回路由文件中的数据(表单)并设置 SESSION 变量
- 您提交表格
- 请求通过路由文件来决定做什么(不是属性的位置
action**)
- 路由文件检查
POST>token对SESSION>token.
- 它们应该匹配,因此路由文件有效地输出指示
true***的数据
- 返回数据
* 您尝试访问的文件是 0 差异;尝试一下,infkdsngfdslghfdslgnfdg.php它仍然会以相同的方式工作。您请求的文件永远不会被访问,它似乎只是因为请求的文件和路由的文件是相同的!
** 如上,你可以将 action 属性设置为几乎任何东西,试试fdsfnldgksdf.php
*** 令牌是否匹配,路由文件仍然输出等同于的数据true
根据@brombeer的测试,这确实按预期工作,那么为什么它不适合你呢?
问题
如果您检查服务器正在运行的命令提示符/终端,您会得到正在发生的事情的流(例如,当请求被接受时等)。您会注意到,如果您在发出请求时看到它,您会得到如下结果:
[DATE] [::1]:XXX01 Accepted
[DATE] [::1]:XXX02 Accepted
[DATE] [::1]:XXX01 Closing
[DATE] [::1]:XXX02 Closing
另一方面, @brombeer会得到如下结果:
[DATE] [::1]:XXX01 Accepted
[DATE] [::1]:XXX01 Closing
这就是问题。您正在向@brombeer的一个请求发出两个请求,并且两个请求都通过路由文件。
第一个请求是您期望的请求,并且您会得到预期的输出。但是,在您收到该输出后,第二个请求运行(遵循与上述完全相同的流程 - 请记住,请求什么文件并不重要,脚本将输出相同的内容(!) - 并有效地$_SESSION["token"]将随机数。
如果您更改,这可能会更容易看到...
$_SESSION["token"] = rand();
...至...
$_SESSION["token"]++;
第二个要求是什么?
这与 PHP 无关;这完全与您的浏览器有关。浏览器对所请求文件以外的各种事物提出请求。例如:
- JavaScript 文件
- CSS 文件
- 页面上使用的图像
当然,在这个例子中你没有使用任何一个。但是,无论您是否告诉它们,浏览器都会寻找一些资源:通常基于上下文。
在这种情况下,您的浏览器足够聪明,可以知道您正在尝试访问一个网站(可能是因为端口号,但也可能是因为请求方法或 URI)。
因此,它会尝试找到一些希望在网站上找到的其他文件,特别是:(favicon.ico您应该能够在 Bowser 的开发工具中看到此请求Network)。
index.php正如已经解释的那样,因为您已经使用路由文件设置了服务器,所以请求与or请求经历相同的过程fnjksgjfndsglkjnsf.php。事实上,甚至从未寻找过实际的图标文件。
您可以通过将此代码添加到文件顶部来进一步证明这一点...
if (!strpos($_SERVER["REQUEST_URI"], ".php")) {
return false;
}
如果请求的文件不是文件,这将停止在您的路由文件中执行php。另外因为我们返回false服务器会寻找图标文件。返回true也可以,但不会查找图标文件。
您也可以尝试将端口更改为类似的东西:8030,我希望代码会按您的预期工作(因为浏览器不会请求网站图标)。
解决方案
回到我对这个问题的第一条评论......
在这种情况下,为什么要将文件传递给服务器?
我仍然不确定您为什么这样做:我认为这是因为您不了解路由文件的作用?或者你不明白你正在创建一个路由文件?
希望我们已经在这里清除了?
无论哪种方式,我都相当确定设置 arouting file不是您想要的,并且出于您的目的,它似乎也不是您需要的。
所以只是不要添加index.php到命令的末尾。
其他工作示例
将您的替换index.php为以下代码:
session_start();
echo "<pre>";
if (!empty($_POST['token'])) {
var_dump($_POST['token'], $_SESSION['token']);
exit;
}
$_SESSION['token']++;
echo '<form action="indasdasfdex.php" method="post"><input name="token" value="' . $_SESSION['token'] . '"><input type="submit" value="submit"></form>';
var_dump($_POST['token'] ?? null, $_SESSION['token'] ?? null);
使用作为路由器文件运行您的服务器index.php(根据您的原始问题):
php -S localhost:8888 index.php
// Because you require `index.php` in your `server.php`
// this will work the same if you use `server.php` instead
这就是发生的事情
要求:index.php
Router file runs `$_SESSION["token"] == 1`
Router file returns data to browser with a form: `"token" == 1`
Request terminated
Browser shows returned data
Form: `token.value == 1`
`var_dump` output
`$_POST["token"] == null`
`$_SESSION["token"] == 1`
要求:favicon.ico
Router file runs `$_SESSION["token"] == 2`
Router file returns data to browser with a form `"token" == 2`
Request terminated
Browser doesn't show returned data (but you can see it in dev tools)
_Not shown because an image isn't returned!_
_Can be seen in dev tools_
Form: `token.value == 2`
`var_dump` output
`$_POST["token"] == null`
`$_SESSION["token"] == 2`
请求:提交表格到index.php
Router file runs
Dumps `$_SERVER["token"]` and `$_POST["token"]` (2,1)
Router file `exit`
Request terminated
Browser shows returned data
`var_dump` output
`$_POST["token"] == 1`
`$_SESSION["token"] == 2`
要求:favicon.ico
Router file runs `$_SESSION["token"] == 3`
Router file returns data to browser with a form `"token" == 3`
Request terminated
Browser doesn't show returned data (but you can see it in dev tools)
_Not shown because an image isn't returned!_
_Can be seen in dev tools_
Form: `token.value == 3`
`var_dump` output
`$_POST["token"] == null`
`$_SESSION["token"] == 3`**