Foreach 仅在选中时才选择第一个复选框

Posted

技术标签:

【中文标题】Foreach 仅在选中时才选择第一个复选框【英文标题】:Foreach is picking the first checkbox only if checked 【发布时间】:2016-08-05 15:08:00 【问题描述】:

我正在编写以下代码,以便从表单中选择复选框。如果我选中第一个复选框,一切都会很好。如果我选中另一个复选框,我会在发送bulkcopy 表单时收到“未定义索引”错误。请记住,由于表单和字段位置的复杂性,我正在使用 post 方法获取复选框,并且提交按钮位于复选框上方。我基本上需要的是选择多个复选框并将某些值添加到数据库中。

<?php //bulkcopy.php

  session_start();
  if($_SESSION['admin_logged_in'] != true)
    header("Location:login.html");
    exit();
  
  include 'db.php';

  $from = mysql_real_escape_string($_GET['from']);
  $room = mysql_real_escape_string($_POST['room']);

  if(!empty($_POST['id'])) 
    foreach($_POST['id'] as $check) 
      $id = $check;

      $sel = mysql_query("select * from $from where id = '$id' limit 1 ") or die(mysql_error());

      while($row = mysql_fetch_array($sel))
        $preview = $row['preview'];
        $text = $row['text'];
        $title = $row['title'];
        $images = $row['images'];
      

      $ins = mysql_query("insert into $room (id, preview, text, title, images) values (' ', '$preview', '$text', '$title', '$images') ") or die(mysql_error());

    

    header("Location:admin.php");
  

?>

表格代码如下:

<form class="form-inline" name="bulkcopy" method="post" action="bulkcopy.php?from=sights"> <b>Bulk Copy:</b> 
    <select name='room' class="form-control">
        <option>Select...</option>
        <option value="Orhan">Orhan</option>
        <option value="Deniz">Deniz</option>
        <option value="Irini">Irini</option>
        <option value="Katina">Katina</option>
        <option value="Gulbin">Gulbin</option>
        <option value="Mihalis">Mihalis</option>
    </select>
    <input class="btn btn-primary" type="submit" name="submit" value="Go"><br /><br />
</div>
<table class="table table-bordered table-striped">
    <th>Entry Name</th>
    <th>Display Order</th>
    <th>Copy to...</th>
    <th>Status</th>
    <th>Image</th>
    <th>Edit</th>
    <th>Delete</th>
    <th>Duplicate</th>

    <?php while($row = mysql_fetch_array($sel))  ?>
    <tr>
        <td>
            <input type="checkbox" name="id[]" value="<?php echo $row['id']; ?>">
            </form>
            <?php echo $row['title']; ?>
        </td>
        <td>
            <form name="order" method="post" action="sightorder.php?id=<?php echo htmlspecialchars($row['id']); ?>">
                <div class="col-md-4">
                    <input class="form-control" type="number" name="order" value="<?php echo htmlspecialchars($row['ordernum']); ?>">
                </div>
                <div class="col-sm-3">
                    <input type="submit" name="submit" value="Set Order" class="btn btn-primary">
                </div>
            </form>
        </td>
        <td>

            <form name="copyto" method="post" action="copyto.php?from=sights&id=<?php echo htmlspecialchars($row['id']); ?>">
                <input type="checkbox" name="room[]" value="Orhan"> O -
                <input type="checkbox" name="room[]" value="Deniz"> D -
                <input type="checkbox" name="room[]" value="Irini"> I -
                <input type="checkbox" name="room[]" value="Katina"> K -
                <input type="checkbox" name="room[]" value="Gulbin"> G -
                <input type="checkbox" name="room[]" value="Mihalis"> M 
                <input type="submit" name="submit" value="Copy" class="btn btn-primary">
            </form>

        </td>
        <td>
            <a href="sightstatus.php?id=<?php echo htmlspecialchars($row['id']); ?>&status=<?php echo $row['status']; ?>"><?php if($row['status'] == 1) ?><i class="fa fa-check fa-lg"></i><?php else ?><i class="fa fa-times fa-lg"></i><?php  ?></a>
        </td>
        <td>
            <a href="sightimages.php?id=<?php echo $row['id']; ?>"><i class="fa fa-image fa-lg"></i></a>
        </td>
        <td>
            <a href="editsight.php?id=<?php echo htmlspecialchars($row['id']); ?>"><i class="fa fa-edit fa-lg"></i></a>
        </td>
        <td>
            <a onclick="return confirmDelete()" href="delsight.php?id=<?php echo htmlspecialchars($row['id']); ?>"><i class="fa fa-trash fa-lg"></i></a>
        </td>
        <td>
            <a href="duplicatesight.php?id=<?php echo htmlspecialchars($row['id']); ?>"><i class="fa fa-copy fa-lg"></i></a>
        </td>
    </tr>
    <?php  ?>
</table>

任何帮助将不胜感激。 谢谢。

【问题讨论】:

我已经用表单代码的一部分更新了问题。 请不要使用the mysql_ database extension,它已被弃用(在PHP7中永远消失了)特别是如果您只是学习PHP,请花精力学习PDOmysqli_数据库扩展,@987654322 @ 感谢您的提示。我会的。 还有其他建议可以使此代码正常工作吗? 您对$sel 的查询是什么。 @埃文萨普 【参考方案1】:

你这里有问题

<?php
    while($row = mysql_fetch_array($sel)) ?>
        <tr><td><input type="checkbox" name="id[]" value="<?php echo $row['id']; ?>"> <?php echo $row['title']; ?></td></form>

while 循环没有右括号,添加第一个复选框后表单关闭。因此,如果未选中该复选框,则不会发布输入,因此未定义索引。确保在添加所有行之前不要关闭表单,就像这样

<?php
    while($row = mysql_fetch_array($sel)) ?>
        <tr><td><input type="checkbox" name="id[]" value="<?php echo $row['id']; ?>"> <?php echo $row['title']; ?></td></tr>
<?php  ?>
  </table>
</form>

【讨论】:

这很可能是正确的,应该在尝试其他任何操作之前修复。现代浏览器解决了这个问题,但也许 OP 没有。 我已经更新了表单代码。如您所见,我在代码的同一部分有两种形式,还有一种用于从数据库中获取数据并填充表的 while 循环。由于我不能使用嵌套形式,这是我最好的选择。我试图在表单结束之前关闭 while 括号,但它破坏了其余代码。 现在您的复选框不在任何形式中。我建议您将长行代码分解为适当缩进的格式,以便您可以更轻松地检查结构。【参考方案2】:

在查看了您提供的完整页面的raw HTML 之后,很明显问题在于您正在尝试嵌套多个无效 HTML 表单。请参阅this answer 了解更多信息。这个答案确实链接到a workaround,但它是一个丑陋的黑客,应该避免。

我相信在您的情况下,适当、有效的 HTML 解决方案是使用单一表单。目前您有多个嵌套表单提交到以下位置:

    bulkcopy.php?from=sights sightorder.php?id=1 copyto.php?from=sights&id=1 copyto.php?from=sights&id=46 等等……

您可以做的是使用一个表单,根据单击的提交按钮确定要执行的操作。例如:

switch ($_POST['submit']) 
    case 'Go':
        // process bulkcopy
        break;

    case 'Set Order':
        // process siteorder
        break;

    // etc...

【讨论】:

我已经用表单的完整部分更新了表单代码,以便更容易重现错误。请再次检查。 @EvanSap 您更新后的表单有一个结束 &lt;/form&gt; 标记,没有开始标记,因此复选框不会在任何地方提交。然后你有两个额外的,显然不相关的表格。我仍然无法根据此代码重现错误。 开始标签在表单代码的开头命名为“bulkcopy”。第一行代码。 @EvanSap 不幸的是,我仍然无法重现该错误。我假设您指的是“条目名称”复选框,而不是“复制到”复选框。你有没有机会提供一个活生生的例子?我真的很想帮你解决这个问题。我建议您在提交之前查看表单的源代码,并确保您的所有 id 都已按应有的方式设置。 是的,我指的是“条目名称”。我正在为这个特定问题开发我的本地虚拟机,不幸的是我没有当前更新的实时版本。【参考方案3】:

如果你的变量复选框是一个表 $_POST['id'] 当你这样做的时候

foreach($_POST['id'] as $check) 
  $id = $check;
  ...

如果不检查第一个输入第一个变量

$check = $_POST['id']['0'];  // is empty

你可以在 foreach 中做另一个条件

if(!empty($_POST['id'])) 
  foreach($_POST['id'] as $k=>$v) 

    if(!empty($v))      
       $id = $v;

       $sel = mysql_query("select * from $from where id = '$id' limit 1 ") or die(mysql_error());

       while($row = mysql_fetch_array($sel))
           $preview = $row['preview'];
           $text = $row['text'];
           $title = $row['title'];
           $images = $row['images'];
       

       $ins = mysql_query("insert into $room (id, preview, text, title, images) values (' ', '$preview', '$text', '$title', '$images') ") or die(mysql_error());



    
  

header("Location:admin.php");

【讨论】:

我试过你的方法,结果一样。不幸的是,我仍然收到“未定义索引”错误。还有其他建议吗? 你有桌子 $from 和桌子 $room 吗? 是的,它们定义在第一个 if 语句之上。【参考方案4】:

您的表单没有POST 名称为“房间”的输入。因此,当您尝试使用$room = mysql_real_escape_string($_POST['room']); 这一行进行检查时,$_POST 数组中没有索引为“room”的项,因此出现未定义索引错误。

要调试这种事情,分析表单提交的请求/响应标头会很有帮助。如果您使用 Chrome,请按 Ctrl+Shift+I 调出开发者控制台,选择“网络”选项卡,当您提交表单时,查看弹出条目的详细信息。您将能够在此处看到正在发送的内容的名称和值,并让您了解哪里出了问题。其他浏览器也可用,并且每个浏览器都有自己值得尊敬的版本。

此外,在访问您未定义或无法依赖的任何变量(例如表单提交)之前,您应该使用isset() 确保变量在使用之前存在 - 这将停止错误你得到并且还让你更容易发现哪里出了问题:

if (!isset($_POST['room'])) 
  print('Please select something');
 else 
  $room = $_POST['room']; // technically not needed tho :p
  //...

【讨论】:

房间提交正确。我回显房间变量,我总是得到正确的输出。我已经更新了我的问题中的表单代码,以确保它反映了当前状态。【参考方案5】:

您正在调用哪个页面,sightorder.php 或 copyto.php?通过哪个提交按钮,设置顺序或复制?

在这两种情况下,您都是通过 GET 而不是通过 POST 发送 id。

哪个是产生错误的行?

卢卡

【讨论】:

bulkcopy.php,提交是“开始”按钮。 好的,如果是这样,根据您生成的html,您没有发送任何ID。不是吗?也许我错过了一些可以完成这项工作的 javascripts 其实我没有使用任何js,但问题是我需要发送选中的复选框。根据我从收到的 cmets 中了解到的是,由于 while 循环在关闭表单之前没有右括号,因此如果选中,它只会提交第一个复选框。这是有道理的。我想如果我设法找到一种方法在复选框之前关闭表单但以某种方式用 JS 提交它们也许可以解决。 好的,谢谢!确实如此:您关闭名为 id 且值为 1 的输入复选框正下方的表单标记。我认为您需要一个不同的结构,而 js 可能非常有用。我想您必须将每个选择的 id 和目标房间传递给您的页面。您可以将 Go 元素从提交更改为按钮,并在单击时附加一个事件,该事件会创建一个 id 数组(可能为每个选定元素创建一个隐藏字段)并将数据提交到您的操作页面。我认为这个解决方案可以帮助您处理如此复杂的页面。 嗨,埃文,您能尝试更改您的“开始”按钮,如下所示吗? &lt;input class="btn btn-primary" type="submit" name="button" onclick="serializeIdsAndGo" value="Go"&gt; 然后,您应该添加以下代码:&lt;script type="text/javascript"&gt; function serializeIdsAndGo() $('input[name="id[]"]').each(function(e) if($(this).is(':checked')) $('form[name="bullcopy"]').append('&lt;input type="hidden" name="id[]" value="'+$(this).val()+'"&gt;\n'); $('form[name="bullcopy"]').submit(); ); &lt;/script&gt; 如果它解决了您的问题,请告诉我【参考方案6】:
  <form bulkcopy>
  ....

  <table>
  <?php while: ?>
      // </form> it must be deleted
      ...
      <div sightorder>
         ...
         <input submit onclick="return send_sightorder(this);">
      </div>

      ...
      <div copyto action="copyto.php?from=sights&id=<?php echo htmlspecialchars($row['id']); ?>">
          ...
          <input submit onclick="return send_copy(this);">
      </div>

  <?php end while ?>
  </table>
  </form> // bulkcopy's close tag 
  <script>
     /// Function send_sightorder is same.
     function send_copy(clicked_element) 
         var form = clicked_element.parent;
         var inputs = form.getElementsByTagName("input");
         var data = inputs[0].name + "=" + inputs[0],checked + "&";
         var URL = window.location.host + form.getAttribute("action");     

         for (i=1; i<inputs.length-1; ++i) 
             data = "&" + inputs[i].name + "=" + inputs[i].checked + "&";
         

         xmlhttp = new XMLHttpRequest();
         xmlhttp.onreadystatechange = function() 
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) 
               // redirect to new page or something else ...
               window.location = URL;
            
         
         xmlhttp.open("POST", URL,true);
         xmlhttp.send(data);

         return false;
     
  </script>

【讨论】:

其实我的问题出在批量复制表单上。您指的是 copyto 表单。不过,您能否进一步详细说明 send_copy_inf() 函数? 我更改了我的评论。 send_copy_inf() 不需要。 我会尝试并报告。 对不起,同样的结果很遗憾。我认为关闭打开的技巧没有帮助。 尝试使用 send_copy_inf() 函数的第一个变体。我更新了答案【参考方案7】:

你自己给自己惹了麻烦。

据我所知,您在发送带有“批量复制”按钮的“条目名称”列的多个复选框时遇到问题。

它应该是这样工作的。这是因为您要在“显示顺序”列中关闭表单,这基本上使它只包含其中的第一个复选框。如果要将所有选中的复选框发布到“批量复制”脚本,则必须将其声明为所有复选框的单独表单,或者使用 JS,例如。使用您包含的 jQuery:

// how to collect checked ids of checkboxes.
var ids = [];
var boxes = $('input[name="id[]"]');
for(var i in boxes) 
  if(boxes[i].checked) 
    ids.push(boxes[i]);
  

用例如钩住上面的东西。 on('click') 您的 sumbit 按钮。在 SO 上,有很多示例如何使用 JS 准备和发送表单。

编辑:

还有更简单的方法。您必须在表单中添加 id

<form class="form-inline" name="bulkcopy" id="bulkcopy" method="post" action="bulkcopy.php?from=sights">

然后将您的复选框设置为归它所有:

<input type="checkbox" name="id[]" value="1"  form="bulkcopy">
<input type="checkbox" name="id[]" value="46"  form="bulkcopy">

这应该可以轻松解决您的问题。

不要忘记删除多余的表格结束标签:

// -----------------------------------------------------------v
<input type="checkbox" name="id[]" value="1" form="bulkcopy"></form>

它们以后可能很容易破坏您的解决方案。在提交按钮后立即关闭:

    <input class="btn btn-primary" type="submit" name="submit" value="Go"><br /><br />
</form>

【讨论】:

您能否进一步详细说明您的答案。就 js 和 jquery 而言,我是个菜鸟…… 检查新的尝试;)在w3schools.com/tags/att_input_form.asp找到它【参考方案8】:

在您最后生成的 html 中,您要提交的输入不在 bulkcopy 表单中。正如其他人指出的那样,您应该更改您的 html 标记。在不更改标记的情况下完成这项工作的一种快速方法是使用 javascript。只需将其添加到 html 的底部即可。它将接受您要提交的输入并附加它们到bulkcopy 表单。

    <script>
    $(document).ready(function()
     $('form[name="bulkcopy"]').submit(function( event ) 
     $('input[name="id[]"]').clone().hide().appendTo($(this) );
   );
   );
    </script>

你也应该使用mysql_num_rows()来检查你是否真的有结果,然后再尝试访问它们并将它们用于插入数据库。你的代码的问题是里面的变量

 while($row = mysql_fetch_array($sel))
   ....
   

如果结果集为空,则永远不会定义它们。但是尽管它们从未定义过,但您稍后尝试在插入查询中使用它们。所以先检查您是否有结果:

 <?php
session_start();
 if($_SESSION['admin_logged_in'] != true)
  header("Location:login.html");
  exit();

 include 'db.php';

$from = mysql_real_escape_string($_GET['from']);
$room = mysql_real_escape_string($_POST['room']);

if(isset($_POST['id'])&&!empty($_POST['id'])) 
foreach($_POST['id'] as $check) 
  if(empty($check)) continue;
  $id = $check;

  $sel = mysql_query("select * from $from where id = '$id' limit 1 ") or die(mysql_error());

if(mysql_num_rows($sel)>0)
  while($row = mysql_fetch_array($sel))
    $preview = $row['preview'];
    $text = $row['text'];
    $title = $row['title'];
    $images = $row['images'];
 

  $ins = mysql_query("insert into $room (id, preview, text, title, images) values (' ', '$preview', '$text', '$title', '$images') ") or die(mysql_error());

 



header("Location:admin.php");


?>

【讨论】:

不幸的是,结果相同。一旦我选择了第一个以外的复选框,脚本就会以白屏结束,报告“未定义的索引 id”。如果我选择第一个和另一个,它只将第一个存储到数据库中。 可能你的 php 生成的 html 有问题,除了第一个复选框之外的所有复选框都没有值......我只是添加了一个检查以查看 $_POST['id']已设置。这将防止显示 BUT 的错误,以便将其他复选框保存到数据库中,它们必须提供有效的 id。如果它仍然不起作用,请告诉我错误发生在脚本的哪一行,并提供您的 html 结构(只需从您的浏览器查看源代码)和您的帖子数据(只需将var_dump($_POST);exit(); 放在您的代码顶部... 第 16 行未定义索引。发布数据:array(2) ["room"]=> string(5) "Orhan" ["submit"]=> string(2) "Go" 第 16 行是什么?在你的脚本中?你确定你粘贴我的代码?此外,您没有发布 id,因此可以肯定您的 html 存在问题 $_POST 只有两个元素“room”和“submit”。“id”不存在,因此当然不会将任何内容保存到数据库中。您的复选框没有名字。所以你必须显示你生成的html(只是“从你的浏览器查看源代码”)。 请在此处找到生成的 html:pastebin.com/j3DN5iwP

以上是关于Foreach 仅在选中时才选择第一个复选框的主要内容,如果未能解决你的问题,请参考以下文章

如何使引导复选框组在选中时关闭另一个组中的所有复选框

该复选框在未选中时不能返回 False,但在选中时可以返回 True

仅在选中时读取 GTK 单选按钮信号

JTable Checkbox 应在选中时启动计时器

只允许选中一个复选框 - asp.net c#

仅在至少选中一个复选框时才使用外部提交按钮提交表单