为啥复选框状态并不总是传递给 PHP 脚本?

Posted

技术标签:

【中文标题】为啥复选框状态并不总是传递给 PHP 脚本?【英文标题】:How come checkbox state is not always passed along to PHP script?为什么复选框状态并不总是传递给 PHP 脚本? 【发布时间】:2011-02-01 00:47:43 【问题描述】:

我有一个 html 表单:

<form action='process.php' method='post'>
  <input type='checkbox' name='check_box_1' /> Check me!<br>
</form>

这是来自 PHP 脚本process.php 的部分:

echo (isset($_POST['check_box_1']))?'Set':'Not set';

设置复选框时脚本的输出是

设置

但是当没有设置复选框时,输出是:

未设置

这是为什么?这似乎是一个非常糟糕的设计,因为我的 PHP 脚本检查了许多 $_POST 变量以确保它们被传递给脚本。当$_POST['check_box_1']值没有设置时,我怎么知道是脚本没有传递值还是复选框没有设置?

【问题讨论】:

【参考方案1】:

不幸的是,这就是提交表单中复选框规范的工作方式 - 如果未选中复选框,浏览器根本不一定会发送该字段。

【讨论】:

这是一个非常糟糕的设计理念!还是谢谢。【参考方案2】:

只有选中复选框的值才会提交给服务器。这是 HTML/浏览器设计的东西,与 PHP 无关。您还如何可靠地区分选中的复选框和未选中的复选框?

...那我怎么知道是脚本没有传递值还是没有设置复选框?

您可以相信浏览器和 PHP 会正确处理。如果未设置,则未选中该框。如果您正在运行一些 javascript 来提交表单并且可能会出错,那么您有责任调试您的脚本。


关于“这是糟糕的设计”:

这是高效的设计。考虑到值仅作为文本发送的限制,只有其他两种可能性:

    分别发送值和状态,如checkbox:state=checked&amp;checkbox:value=myvalue。让我们假装一下,这不会对输入元素名称允许的内容和不允许的内容造成严重的麻烦和歧义。 使用魔法值表示“未检查”:checkbox=false。这意味着我不能制作这样的复选框:&lt;input type="checkbox" name="checkbox" value="false" /&gt;

让我们假设将使用上述任一解决方案并且与它们相关的问题将得到解决。这意味着对于页面上的每个复选框都会发送一个 POST 值。通常这没什么大不了的,但让我们想象一个有 50 个复选框的页面。我会说不是太不切实际。一个有200的呢?这是每个 POST 的 HTTP 标头中额外的 200 * ~10+ 字符,可能大多数只是告诉您用户做了什么没有

由于这种技术是在带宽非常宝贵的时候发明的,所以最有效的方法是简单地发送未选中复选框的值。

【讨论】:

简单:check_box_1=truecheck_box_1=false 问题是一些在网络上漫游的恶意机器人可能会请求该页面 - 因为它会在没有设置复选框字段的情况下请求该页面,所以我必须像提交未设置复选框的表单。 @George 发送的 HTTP 协议只发送没有类型的文本。如何区分值为"false" 的复选框和未设置的复选框? @George 所以...?您如何区分未选中该框的机器人和未选中该框的用户?无论如何,这是错误的信息。 @deceze:你误解了我的意思。实际的 POST 文本将是 check_box_1=truecheck_box_1=false【参考方案3】:

如果你想克服这个设计特点,试试这个:

<input type="hidden" name="check_box_1" value="0" />
<input type="checkbox" name="check_box_1" value="1" />

这样,您将始终在回调页面中设置$_POST['check_box_1'],然后您只需检查其值即可查看他们是否检查了它。不过,这两个输入必须按此顺序排列,因为后一个将优先。

【讨论】:

如果您有多个选择,例如 ,则无法正常工作【参考方案4】:

nickf 提供了最佳答案,但是当您有多个同名复选框时,它在特殊情况下不起作用。相反(如果您使用的是 jQuery),您可以使用假复选框来切换真实的隐藏输入的值,如下所示:

<input type="checkbox" onclick="$(this).next().val(this.checked?1:0)"/>
<input type="hidden" name="verified[]"/>

<input type="checkbox" onclick="$(this).next().val(this.checked?1:0)"/>
<input type="hidden" name="verified[]"/>

请注意,只有隐藏的复选框被命名。

【讨论】:

【参考方案5】:

是的,这是糟糕的设计,肯定不是“高效”的设计,原因如下:

复选框是一个控件,允许用户从一组一个或多个选项中选择零个或多个值。

通过不发送未经检查的值,浏览器强制表单处理程序“知道”它应该从表单中得到什么,并假设缺失值意味着“我不想要那个选项”。当您在某处更新记录时,这是灾难性的,因为您不能依赖提交的信息来完成。

您基本上不知道缺少的复选框是否意味着“用户不希望设置该选项”与“用户未提供任何信息”。前者要求您更新记录,而后者则不需要。

这使得部分表单(允许用户更新部分记录)在没有大量额外工作的情况下绝对不可能,当您的表单有大量复选框时尤其可怕。

您基本上必须首先明确查找应该存在的信息,然后推断用户希望它在丢失时“未设置”。

如果将不包含复选框的部分表单提交给同一个处理程序,它将错误地假设用户希望这些选项“未设置”,而实际上没有关于此事的任何信息。

这使得后端的代码重用变得非常困难。

【讨论】:

以上是关于为啥复选框状态并不总是传递给 PHP 脚本?的主要内容,如果未能解决你的问题,请参考以下文章

HTML 复选框元素未将值传递给 jQuery 和 AJAX 字符串

将复选框值传递给 javascript 和 PHP 邮件

通过 Ajax 将多个复选框传递给 PHP

如何将多个复选框值传递给php [重复]

为啥不传递更新的元素值?

如何将一组选中/未选中的复选框值传递给 PHP 电子邮件生成器?