-1

I've a webpage that picks values from a database and populates a table for attendance. The radio buttons are created dynamically and assigned IDs from the database however, when I submit the entries, the database remains blank.

<?php
require __DIR__ . "/connection/connect.php";
?>
<!DOCTYPE html>
<html>

<head>
  <title>Attendance</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="css/font-awesome.min.css" type="text/css">
  <link rel="stylesheet" href="css/bootstrap-4.3.1.css">
</head>

<body>
  <nav class="navbar navbar-expand-lg navbar-light">
    <div class="container"> <button class="navbar-toggler navbar-toggler-right border-0 p-0" type="button" data-toggle="collapse" data-target="#navbar8">
        <p class="navbar-brand text-primary mb-0">
          <i class="fa d-inline fa-lg fa-stop-circle"></i> BRAND </p>
      </button>
      <div class="collapse navbar-collapse" id="navbar8">
        <ul class="navbar-nav mr-auto">
          <li class="nav-item"> <a class="nav-link" href="#">Home</a> </li>
          <li class="nav-item"> <a class="nav-link" href="#">Reports</a> </li>
          <li class="nav-item"> <a class="nav-link" href="#">About</a> </li>
        </ul>
        <p class="text-primary d-none d-md-block lead mb-0"> <i class="fa fa-expeditedssl" aria-hidden="true"></i> <b> CLASS ATTENDANCE</b> </p>
        <ul class="navbar-nav ml-auto">
          <li class="nav-item mx-1"> <a class="nav-link" href="#">
              <i class="fa fa-file-text fa-fw fa-lg"></i>
            </a> </li>
          <li class="nav-item mx-1"> <a class="nav-link" href="#">
              <i class="fa fa-sign-out fa-fw fa-lg"></i>
            </a> </li>
        </ul>
      </div>
    </div>
  </nav>
  
  <form method="POST" action="submit.php">
  <div class="py-5">
    <div class="container">
      <div class="row">
        <div class="col-md-12">
          <div class="table-responsive">
            <table class="table table-bordered ">
              <thead class="thead-dark">
                <tr>
                  <th>Name</th>
                  <th>Sex</th>
                  <th>Attendance</th>
                </tr>
              </thead>
              <tbody>
                <?php
                $query = " SELECT * FROM `students` WHERE class = 'Year 7 -' ORDER BY stud_name ASC "; 
                if($result = $conn->query($query)){
                  while ($rows = $result->fetch_assoc()){
                   
                    echo"
                    <tr>
                      <td>".$rows['stud_name']."</td>
                      <td>".$rows['gender']."</td>
                      <td><input type='radio' name=".$rows['stud_no']." value='present'> <label>Present</label>       <input type='radio' name=".$rows['stud_no']." value='absent'> <label>Absent</label></td>
                    </tr>";
                  }
                }
                else{
                  echo "<div class='alert alert-danger' role='alert'> No records found </div>";
                }
                ?>
                </tbody>
            </table>
          </div>
        </div>
      </div>
      <center><div class="row">
        <div class="col-md-4"><button class="btn btn-primary" id="submit">Submit Attendance</button></div>
      </div></center>
    </div>
  </div></form>
  <div class="py-3">
    <div class="container">
      <div class="row">
        <div class="col-md-12 text-center">
        </div>
      </div>
    </div>
  </div>
  <script src="js/jquery-3.3.1.slim.min.js"></script>
  <script src="js/popper.min.js"></script>
  <script src="js/bootstrap.min.js"></script>
</body>
<?php

if(isset($_POST['submit'])){
    $stud_name = $_POST['stud_name'];
    $stud_no = $_POST['stud_no'];

      $insert = mysqli_query($conn,"INSERT INTO logs (`date`,`stud_name`,`status`) VALUES (now(),'$stud_name','$stud_no')");
  
}
    ?>
</html>

This is the output.

I need to send the radio button values for each individual to the database. I've searched online but i've not found a solution as yet.

RWKSHJ
  • 1
  • 2
  • why are you logging the `stud_name` rather than `stud_no` value? Surely two or more students can have the same name bubt never the same `stud_no` value – Professor Abronsius Aug 16 '22 at 07:32
  • 1
    **Warning:** You are wide open to [SQL Injections](https://php.net/manual/en/security.database.sql-injection.php) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/32391315) – Dharman Aug 16 '22 at 11:31

3 Answers3

1

Rather than assigning stud_noas the name of the radio button you should used that as an array key. The input element should be named something like studno[] but use the value from the db

In the loop, perhaps something like this:

printf(
    '<tr>
        <td>%1$s</td>
        <td>%2$s</td>
        <td>
            <label><input type="radio" name="student[%3$s]" value="1" />Present</label>
            <label><input type="radio" name="student[%3$s]" value="0" />Absent</label>
        </td>
    </tr>',
    
    $rows['stud_name'],
    $rows['gender'],
    $rows['stud_no']
);

In the POST array there will be a student parameter with multiple values and you can easily iterate through those to then assign in the db.


A working mockup to illustrate how you can use the stud_no as a key within the input element's name and subsequently use that to populate the logs table.

<?php

    chdir('../../dbo');
    require 'db-conn-details.php';
    require 'mysqli-conn.php';
    
    
    
    if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_POST['student'] ) ){
        
        # To my mind it makes more sense to log the `stud_no` rather than the
        # `stud_name` ( which I don't see in the form anyway )
        # Use a Prepared Statement to mitigate sql injection
        
        /*
            mysql> describe logs;
            +---------+---------------------+------+-----+-------------------+----------------+
            | Field   | Type                | Null | Key | Default           | Extra          |
            +---------+---------------------+------+-----+-------------------+----------------+
            | id      | int(10) unsigned    | NO   | PRI | NULL              | auto_increment |
            | date    | timestamp           | NO   |     | CURRENT_TIMESTAMP |                |
            | stud_no | varchar(50)         | NO   |     | NULL              |                |
            | status  | tinyint(3) unsigned | NO   |     | 0                 |                |
            +---------+---------------------+------+-----+-------------------+----------------+
            
            Because `date` is a `timestamp` field we do not need supply that in the sql command
        */
        
        $sql='insert into `logs` ( `stud_no`,`status` ) values ( ?, ? );';
        $stmt=$db->prepare( $sql );
        $stmt->bind_param('si', $studno, $status );
        
        foreach( $_POST['student'] as $studno => $status ){
            $stmt->execute();   
        }
        
        $stmt->close();
        exit( header('Location: ?attendance=taken') );
        
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title></title>
    </head>
    <body>
        <form method="POST">
            <table>
            <?php
            
                // emulat e your original query for the sake of example
                $sql='select 
                            `StudentFirstName` as `stud_name`,
                            `StudentRegID` as `stud_no`,
                            case when floor(rand() * ((1-0)+1))=1 then
                                "Male"
                            else
                                "Female"
                            end as `gender` 
                        from  `attendance_master` 
                        order by rand() 
                        limit 10';
                        
                $res=$db->query( $sql );
                while( $rs=$res->fetch_object() ){
                    
                    printf(
                        '<tr>
                            <td>%1$s</td>
                            <td>%2$s</td>
                            <td>
                                <label><input type="radio" name="student[%3$s]" value="1" />Present</label>
                                <label><input type="radio" name="student[%3$s]" value="0" />Absent</label>
                            </td>
                        </tr>',
                        
                        $rs->stud_name,
                        $rs->gender,
                        $rs->stud_no
                    );
                }
            ?>
            </table>
            <input type='submit' />
        </form>
    </body>
</html>

Which yields a display like this:

Example

The resultant POST array looks like this:

Array
(
    [student] => Array
        (
            [13KQC31001] => 1
            [13KQC31006] => 0
            [13KQC31007] => 1
            [13KQC31009] => 1
            [13KQC31010] => 1
            [13KQC31011] => 0
            [13KQC31012] => 1
            [13KQC31015] => 1
            [13KQC31016] => 0
            [13KQC31017] => 1
        )

)

After submitting the form, a simple query to illustrate success:

mysql> select * from logs;
+----+---------------------+------------+--------+
| id | date                | stud_no    | status |
+----+---------------------+------------+--------+
|  1 | 2022-08-16 08:58:46 | 13KQC31001 |      1 |
|  2 | 2022-08-16 08:58:46 | 13KQC31006 |      0 |
|  3 | 2022-08-16 08:58:46 | 13KQC31007 |      1 |
|  4 | 2022-08-16 08:58:46 | 13KQC31009 |      1 |
|  5 | 2022-08-16 08:58:46 | 13KQC31010 |      1 |
|  6 | 2022-08-16 08:58:46 | 13KQC31011 |      0 |
|  7 | 2022-08-16 08:58:46 | 13KQC31012 |      1 |
|  8 | 2022-08-16 08:58:47 | 13KQC31015 |      1 |
|  9 | 2022-08-16 08:58:47 | 13KQC31016 |      0 |
| 10 | 2022-08-16 08:58:47 | 13KQC31017 |      1 |
+----+---------------------+------------+--------+

I hope this illustrates how you can easily use the student_ID or stud_no within the input element and then use that to update the database.

Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
  • Thank you for the reply. When I try out your sample code, I get **Fatal error: Uncaught Error: Call to a member function fetch_object() on bool** error – RWKSHJ Aug 16 '22 at 13:14
  • Are you using PDO or mySQLi? – Professor Abronsius Aug 16 '22 at 13:18
  • Am using mysqli – RWKSHJ Aug 16 '22 at 13:20
  • Technically you do not need to change your `select` query ( which is where I presume the error is originating ) - I added the above SQL query so that I could test the whole code. The SQL query is pertinent to **my** database so provided you generate the HTML with the `stud_no` as the key within the input name ( name='student[xxx]' - denoted by xxx )you could continue using your original code to create the table. – Professor Abronsius Aug 16 '22 at 13:26
0

You should use Jquery when click event and when you click Submit you use Ajax to request server and store.

Don't forget jquery CDN https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js

<form>
    <div>
      <p>name: Ex</p>
      <input class="checkAttend" type='radio' data-student="ex" name="stud_no_1" value='present'> present
      <input class="checkAttend" type='radio' data-student="ex" name="stud_no_1" value='absent'> absent
    </div>
    
    <hr>
    
    <div>
      <p>name: Bx</p>
      <input class="checkAttend" type='radio' data-student="bx" name="stud_no_2" value='present'> present
      <input class="checkAttend" type='radio' data-student="bx" name="stud_no_2" value='absent'> absent
    </div>
    
    <hr>
    
    <button class="submit">Submit</button>
</form>

<script>
$(document).ready(function(){
  $array = [];
  $(".checkAttend").click(function() {
    $stud_no = $(this).attr('name');
    $stud_name = $(this).data('student');
    $value = $(`input[name="${$stud_no}"]:checked`).val();
    // Before push array, you check stud_name is exist ? update status : dont push array
   $array.push({'stud_name': $stud_name, 'status': $value});
   
   console.log($array);
   result: [
              0: {stud_name: 'ex', status: 'present'},
              1: {stud_name: 'bx', status: 'absent'}
           ]
   
})

$(".submit").click(function() {
  $.ajax({
    url: "submit.php",  
    data: array,
    success: function(data) {
      console.log(data);
    },
    error: function(er) {
      console.log(er);
  });
})
  
});
<script>


LihnNguyen
  • 632
  • 4
  • 10
-1

From what I see you are missing the attribute name="submit" from the submit button element

You should have

<button class="btn btn-primary" id="submit" name="submit">Submit Attendance</button>

In this way the condition:

if(isset($_POST['submit'])){

will be caught