8

I am working on the following code in order to pick checkboxes from a form. If i check the first checkbox everything works great. If i check another checkbox i get the "Undefined index" error when sending bulkcopy form. Keep in mind that i am getting the checkboxes with post method and the submit button is above the checkboxes due to the complexity of the location of the form and the fields. What i need essentially is to pick multiple checkboxes and add certain values to the database.

<?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");
  }

?>

The code of the form can be found below:

<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>

Any help would be greatly appreciated. Thanks.

yergo
  • 4,761
  • 2
  • 19
  • 41
vsapountzis
  • 618
  • 3
  • 11
  • 28
  • I have update the question with a part of the form code. – vsapountzis Apr 14 '16 at 07:54
  • 5
    Please dont use [the `mysql_` database extension](http://stackoverflow.com/questions/12859942/why-shouldnt-i-use-mysql-functions-in-php), it is deprecated (gone for ever in PHP7) Especially if you are just learning PHP, spend your energies learning the `PDO` or `mysqli_` database extensions, [and here is some help to decide which to use](http://stackoverflow.com/questions/12859942/why-shouldnt-i-use-mysql-functions-in-php) – RiggsFolly Apr 14 '16 at 08:05
  • Thanks for the tip. I will. – vsapountzis Apr 14 '16 at 08:14
  • Any other suggestions to make this code work? – vsapountzis Apr 15 '16 at 19:37
  • What is your query for `$sel`. @EvanSap – Jatin Raikwar Apr 27 '16 at 12:35
  • I select everything from the table where the id equals to the chosen id of the selected entries. – vsapountzis Apr 27 '16 at 13:32
  • Can you provide the full error message? Which line is throwing the Undefined index? – aynber Apr 27 '16 at 14:28
  • For what I can see after reformatting your code, is that you have an erroneus html. Or at least this `` right after `id[]` checkbox suggests that. Please provide us a minimal working code that reproduces your problem, without PHP over html file, just generated html. Also some more information about errors you receive should be helpful. – yergo May 02 '16 at 08:19
  • @yergo Please find the genrated html here: http://pastebin.com/j3DN5iwP – vsapountzis May 02 '16 at 13:20

8 Answers8

2

You have a problem here

<?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>

There is no closing bracket for the while loop, and the form is closed after the first checkbox is added. So if that checkbox is not checked, then the input is not posted, thus the undefined index. Make sure you do not close the form until after all the rows have been added, like this

<?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>
Arleigh Hix
  • 9,990
  • 1
  • 14
  • 31
  • This is most likely correct and should be fixed before trying anything else. Modern browsers fix this but, maybe the OP's does not. – smcjones Apr 29 '16 at 14:35
  • I have updated the form code. As you can see, i have two forms in the same part of code and one while loop to fetch the data from database and populate the table. Since i cannot use nested forms this is my best option. I have tried to close the while bracket before the form end but it breaks the rest of the code. – vsapountzis Apr 29 '16 at 20:01
  • Now your checkboxes are not within any form. I suggest you break long lines of code into a properly indented format so that you can more easily inspect the structure. – Arleigh Hix Apr 29 '16 at 20:16
1

After reviewing the raw HTML of the complete page you provided, it is clear that the problem is you're trying to nest multiple forms which is invalid HTML. Please refer to this answer for more information. This answer does link to a workaround, but it's an ugly hack and should probably be avoided.

I believe the appropriate, valid HTML solution in your case is to use a single form. Currently you have multiple nested forms submitting to the following locations:

  1. bulkcopy.php?from=sights
  2. sightorder.php?id=1
  3. copyto.php?from=sights&id=1
  4. copyto.php?from=sights&id=46
  5. etc...

What you can do is have a single form that determines which action to take based on which submit button was clicked. For example:

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

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

    // etc...
}
Community
  • 1
  • 1
mister martin
  • 6,197
  • 4
  • 30
  • 63
  • I have updated the form code with the full part of the form so it would be easier to reproduce the error. Please chekck again. – vsapountzis Apr 29 '16 at 20:06
  • @EvanSap your updated form has a closing `` tag with no opening tag, so the checkboxes aren't submitting anywhere. Then you have two additional, apparently unrelated forms. I am still unable to reproduce the error based on this code. – mister martin Apr 29 '16 at 20:34
  • The opening tag is named "bulkcopy" in the beginning of the form code. First line of code. – vsapountzis Apr 29 '16 at 20:39
  • @EvanSap I am still unable to reproduce the error, unfortunately. I assume you're referring to the "entry name" checkboxes and not the "copy to" checkboxes. Is there any chance you can provide a live example? I would really like to help you resolve this issue. I recommend viewing the source code of the form, before you submit it, and make sure all of your id's are set like they should be. – mister martin Apr 29 '16 at 20:50
  • Yes I am referring to the "Entry name". I am working on my local VM for this particular issue and I don't a have live version of the current update unfortunately. – vsapountzis Apr 29 '16 at 21:08
  • Please find the genrated html here: pastebin.com/j3DN5iwP – vsapountzis May 02 '16 at 13:23
0

if you the variable checkbox is a table $_POST['id'] the when you do this

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

if you don't check the first input the first variable

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

you can do another condition in the 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");
}
Fahmi B.
  • 758
  • 2
  • 10
  • 23
0

In your last generated html the inputs you want to submit are not inside bulkcopy form. As others pointed out you should change your html markup.One fast way to make this work without altering your markup is to use javascript.Just add this to the bottom of your html.It will take the inputs you want to be submitted and append them to the bulkcopy form.

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

Also you should use mysql_num_rows() to check if u actually have result before trying to access them and use them for insertion to database.The problem with your code is that the variables inside

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

are never defined in case the result set is empty.But although they are never defined you try to use them in an insert query later.So just check if you have results first:

 <?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");
}

?>
George Pant
  • 2,079
  • 1
  • 9
  • 14
  • Same results unfortunately. As soon as i pick a checkbox other than the first the scripts ends in white screen reporting "undefined index id". If i choose the first and another one it stores only the first to the database. – vsapountzis Apr 27 '16 at 13:31
  • Probably there is a problem with your php generated html and all the checkboxes except the first dont have a value......I just added a check to see if $_POST['id'] is set .That will prevent the error showing BUT in order for the other checkboxes to be saved to the database they must provide valid ids. If it stills does not work tell me in which line of the script the error occurs and also give your html structure (just view source from your browser ) and your post data (just put`var_dump($_POST);exit();` in top of your code... – George Pant Apr 27 '16 at 14:01
  • Undefined index on line 16. Post data: array(2) { ["room"]=> string(5) "Orhan" ["submit"]=> string(2) "Go" } – vsapountzis Apr 28 '16 at 18:38
  • What is on line 16? in your script ? are you sure you paste my code? Also you do not post an id so for sure there is a problem with your html $_POST has only two elements "room" and "submit"."id" is not there so of course nothing will be saved to the database.Your checkboxes do not have name .So you must show your generated html (just "view source from your browser"). – George Pant Apr 28 '16 at 20:07
  • Please find the genrated html here: pastebin.com/j3DN5iwP – vsapountzis May 02 '16 at 13:24
  • I edited my answer based on the generated html you provided.Just use the javascript i provide and dont forget to make the changes in the php file too. – George Pant May 05 '16 at 17:02
0

Your form does not POST an input with the name 'room'. Therefore, when you try and check it with this line $room = mysql_real_escape_string($_POST['room']);, there is no item in the $_POST array with the index 'room', hence the undefined index error.

To debug this kind of thing, it's helpful to analyse the request/response headers of your form submission. If you use Chrome, press Ctrl+Shift+I to bring up the developer console, select the Network tab, and when you submit your form, view the details of the entry that pops up. You will be able to see here the names and values of the things being sent and will give you an idea of where things are going wrong. Other browsers are available, and each have their own respectable versions of this.

Also, before accessing any variables you didn't define yourself, or can't rely on (such as form submissions), you should use isset() to make sure the variable exists before using it - that will stop the error you are getting and also allow you to catch where it's going wrong more easily:

if (!isset($_POST['room'])) {
  print('Please select something');
} else {
  $room = $_POST['room']; // technically not needed tho :p
  //...
}
Alfie
  • 2,341
  • 2
  • 28
  • 45
  • The room is submitted correctly. I echo the room variable and i get the correct output always. I have updated the form code in my question to make sure it reflects the current state. – vsapountzis Apr 28 '16 at 18:35
0
  <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>
0

which is tha page you are callling, sightorder.php or copyto.php? by which submit button, set order or copy?

in both cases you are sending the id by GET not by POST.

which is the line which produces the error?

Luca

luca3003
  • 109
  • 8
  • bulkcopy.php and the submit is the "Go" button. – vsapountzis May 03 '16 at 13:14
  • ok, if so, according to your generated html, you are not sending any id. Isn't it? Maybe I'm missing some javascripts which does the job – luca3003 May 03 '16 at 13:17
  • Actually I don't use any js, but the problem is that i need to send the selected checkboxes. From what I understand from the comments i received is that since the while loop has no closing bracket before the closing form it only submits the first checkbox if selected. Which makes sense. I imagine that if I manage to find a way to close the form before the checkboxes but submit them somehow with JS maybe it could be resolved. – vsapountzis May 03 '16 at 13:28
  • Ok, thank you! It's true: you close the form tag just below the input checkbox named id and valued 1. I think you need a different structure and js could be really useful. I imagine that you have to pass to your page each id selected and the target room. You can do it changing your Go element from submit to button and attaching an event on click which creates an array of ids (maybe creating a hidden field for each selected element) and submits the data to your action page. I think this solution could help you handling a so complex page. – luca3003 May 03 '16 at 13:49
  • Hi Evan, could you try to change your 'Go' button as showed below? `` Then, you shoud add the following code: `` Let me know if it solves your issue – luca3003 May 03 '16 at 15:26
  • Hi Evan, maybe the javascript was not so accurate and need some testing but its effort is to let you use as many forms as you need and fill a form on demand to bulk copy the records. Tomorrow you could call me in a chat, if you want, to check together. bye. – luca3003 May 03 '16 at 19:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110966/discussion-between-luca3003-and-evan-sap). – luca3003 May 04 '16 at 08:36
0

You made you a problem by yourself.

What i understand, you have troubles sending multiple checkboxes of column "Entry name" with button of "bulk copy".

It is how it should work. It's because you are closing your form in "display order" column, what essentially makes it cointain only first checkbox in it. If you want to post all checked checkboxes to "bulkcopy" script, you will have to either declare it as separate form for all checkboxes, or use JS, eg. with your included 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]);
  }
}

to hook something like above with eg. on('click') of your sumbit button. Here on SO there are pletny of examples how to prepare and send form using JS.

Edit:

there is even easier way. You have to add id to your form:

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

and than set your checkboxes to be owned by it:

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

that should easily fix your issue.

Dont forget to remove excess form closing tags:

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

they may easily corrupt your solution later. Just close immediately after your submit button:

    <input class="btn btn-primary" type="submit" name="submit" value="Go"><br /><br />
</form>
yergo
  • 4,761
  • 2
  • 19
  • 41