skip to Main Content

I’m creating a database that stores student scores, so I wrote a js function that allows the user to add as many scores as they need. However, How do I access the different entries in php to store them in my database? Different elements in every entry have the same id and name, so how do I access the $_POST variable in PHP to put in my database? ChatGPT couldn’t solve this and I couldn’t find information on this anywhere, here is my code:

<!DOCTYPE html>
<html>
<head>
<button onclick = "location.href='index.html'">
              Go Back</button>
  <title>TOEFL Scores</title>
  <script>
    var times=0;
    function addEntry() {
  var container = document.getElementById("entry-container");
  var entry = document.createElement("div");
  entry.innerHTML = `
    <label for="r">Reading Score:</label>
    <input type="number" id="r" name="r"><br>

    <label for="l">Listening Score:</label>
    <input type="number" id="l" name="l"><br>

    <label for="s">Speaking Score:</label>
    <input type="number" id="s" name="s"><br>

    <label for="w">Writing Score:</label>
    <input type="number" id="w" name="w"><br>

    <label for="year">Year:</label>
    <select id="year" name="year">
      <option value=""></option>
      <?php
      $current_year = date('Y');
      for ($i = $current_year; $i >= $current_year - 5; $i--) {
        echo "<option value='$i'>$i</option>";
      }
      ?>
    </select>

    <label for="month">Month:</label>
    <select id="month" name="month">
      <option value=""></option>
      <option value="01">January</option>
      <option value="02">February</option>
      <option value="03">March</option>
      <option value="04">April</option>
      <option value="05">May</option>
      <option value="06">June</option>
      <option value="07">July</option>
      <option value="08">August</option>
      <option value="09">September</option>
      <option value="10">October</option>
      <option value="11">November</option>
      <option value="12">December</option>
    </select>

    <label for="day">Day:</label>
    <select id="day" name="day ">
      <option value=""></option>
      <?php
      for ($i = 1; $i <= 31; $i++) {
        echo "<option value='$i'>$i</option>";
      }
      ?>
    </select>
    <br><br>


    <button onclick="deleteEntry(this)">Delete</button>
    <br><br>
  `;
  container.appendChild(entry);
  times++;
}
function deleteEntry(button) {
  var div = button.parentNode;
  div.parentNode.removeChild(div);
}
  </script>
</head>
<body>
  <h3>TOEFL Scores</h3>
  <form method="post" action="process_score.php">
    <div id="entry-container">
      <!-- Initial entry goes here -->
     
      </div>
    </div>
    <button type="button" onclick="addEntry()">Add Score</button>
    <br><br>
    <button type="submit">Submit</button>
  </form>
</body>
</html>

This was the answer that ChatGPT provided

if ($_SERVER["REQUEST_METHOD"] == "POST") {
  // Loop through each submitted entry
  for ($i = 0; $i < count($_POST['r']); $i++) {
    $reading = $_POST['r'][$i];
    $listening = $_POST['l'][$i];
    $speaking = $_POST['s'][$i];
    $writing = $_POST['w'][$i];
    $year = $_POST['year'][$i];
    $month = $_POST['month'][$i];
    $day = $_POST['day'][$i];

    // Echo the values for this entry
    echo "Reading Score: " . $reading . "<br>";
    echo "Listening Score: " . $listening . "<br>";
    echo "Speaking Score: " . $speaking . "<br>";
    echo "Writing Score: " . $writing . "<br>";
    echo "Test Date: " . $year . "-" . $month . "-" . $day . "<br>";
    echo "<br>";
  }
}

2

Answers


  1. To support the comment made above, an example that simplifies the HTML by removing ID attributes and assigns array syntax style names to form elements. By completing and submitting this form within PHP the individual scores can be accessed by index very easily.

    <?php
        
        # this would be the form action script.
    
        error_reporting( E_ALL );
        ini_set( 'display_errors', 1 );
    
        
        if( $_SERVER['REQUEST_METHOD']=='POST' ){
            
            # variable to populate with individual scores to make it easier to work with
            $scores=array();
            
            /***********************************************************
                re-organise POST results so that each entry within 
                the $scores variable relates to the added form section.
            */
            foreach( $_POST as $name => $void ){
                $record=$_POST[ $name ];
                foreach( $record as $i => $value ){
                    $scores[ $i ][ $name ]=$value;
                }
            }
    
            /*
                $sql='insert into `student_scores` (`reading`,`writing`,`listening`,`speaking`,`testdate`) values (?,?,?,?,?)';
                $stmt=$db->prepare( $sql );
                $stmt->bind_param('sssss',$r,$w,$l,$s,$d);
            */
    
            /************************************************
                Process the scores in whatever way you need
            */
            foreach( $scores as $result ){
                $obj=(object)$result;
                printf(
                    '<div class="result">
                        <div>Reading Score: %s</div>
                        <div>Listening Score: %s</div>
                        <div>Speaking Score: %s</div>
                        <div>Writing Score: %s</div>
                        <div>Test Date: %s-%s-%s</div>
                    </div>',
                    $obj->r,
                    $obj->l,
                    $obj->s,
                    $obj->w,
                    $obj->year,
                    $obj->month,
                    $obj->day
                );
                /*
                    $r=$obj->r;
                    $w=$obj->w;
                    $l=$obj->l;
                    $s=$obj->s;
                    $d=sprintf( '%s-%s-%s', $obj->year, $obj->month, $obj->day );
                    
                    $stmt->execute();
                */
    
            }
        }
    ?>
    <!DOCTYPE html>
    <html lang='en'>
        <head>
            <meta charset='utf-8' />
            <title></title>
            <style>
                body,body *{box-sizing:border-box}
                label{display:inline-block;padding:0.5rem;width:45%;margin:auto;}
                section,
                .result{display:block;margin:1rem 0;border:1px dotted rgba(0,0,0,0.25);padding:0.5rem;}
                input,select{padding:0.25rem}
            </style>
        </head>
        <body>
            <h3>TOEFL Scores</h3>
            
            <form method="post">
                <div id="entry-container"></div>
                <button type="button" onclick="addEntry()">Add Score</button>
                <button type="submit">Submit</button>
            </form>
            
            <script>
    
                <?php
                    /*
                        No need to repeat the PHP multiple times
                        - create the variables once and echo them
                        when needed in Javascript below.
                    */
                    $current_year = date('Y');
                    $years=array();
                    for( $i = $current_year; $i >= $current_year - 5; $i-- ) $years[]=sprintf('<option>%s',$i);
                    $years=implode(PHP_EOL,$years);
                    
                    $days=array();
                    for( $i = 1; $i <= 31; $i++ ) $days[]=sprintf('<option>%s',$i);
                    $days=implode(PHP_EOL,$days);
                    
                ?>
                
                
                function addEntry() {
                  var container = document.getElementById("entry-container");
                  var entry = document.createElement("div");
                  /*
                    Entirely remove the ID attributes and nest the form element
                    within it's own `label` to maintain valid HTML.
                    
                    Assign the "array syntax" to element names, ie: name="fred[]"
                    which enables you to iterate through these in PHP using array
                    methods.
                  */
                  entry.innerHTML = `
                    <section>
                        <label>Reading Score: <input type="number" name="r[]" /></label>
                        <label>Listening Score: <input type="number" name="l[]" /></label>
                        <label>Speaking Score: <input type="number" name="s[]" /></label>
                        <label>Writing Score: <input type="number" name="w[]" /></label>
    
                        <label>Year:
                            <select name="year[]">
                              <option selected hidden disabled>Select Year
                              <?php
                                echo $years;
                              ?>
                            </select>
                        </label>
    
                        <label>Month:
                            <select name="month[]">
                              <option selected hidden disabled>Select Month
                              <option value="01">January
                              <option value="02">February
                              <option value="03">March
                              <option value="04">April
                              <option value="05">May
                              <option value="06">June
                              <option value="07">July
                              <option value="08">August
                              <option value="09">September
                              <option value="10">October
                              <option value="11">November
                              <option value="12">December
                            </select>
                        </label>
    
                        <label>Day:
                            <select name="day[]">
                                <option selected hidden disabled>Select Day
                                <?php
                                    echo $days;
                                ?>
                            </select>
                        </label>
                        
                        <!-- make this a button so that it does not submit the form -->
                        <button type='button' onclick="deleteEntry(event)">Delete</button>
                    </section>`;
                    
                    container.appendChild( entry );
                }
    
                // simplify the delete function by inspecting the `event` to identify elements to delete.
                function deleteEntry(e){
                    e.target.parentNode.parentNode.removeChild( e.target.parentNode )
                }
            </script>
        </body>
    </html>
    

    For example, adding 3 scores and submitting the form will yield results like this:

    Array
    (
        [r] => Array
            (
                [0] => 47
                [1] => 78
                [2] => 34
            )
    
        [l] => Array
            (
                [0] => 1
                [1] => 23
                [2] => 54
            )
    
        [s] => Array
            (
                [0] => 2
                [1] => 0
                [2] => 43
            )
    
        [w] => Array
            (
                [0] => 66
                [1] => 45
                [2] => 77
            )
    
        [year] => Array
            (
                [0] => 2018
                [1] => 2022
                [2] => 2020
            )
    
        [month] => Array
            (
                [0] => 11
                [1] => 07
                [2] => 05
            )
    
        [day] => Array
            (
                [0] => 14
                [1] => 5
                [2] => 4
            )
    )
    

    The PHP that processes the POST results would then produce HTML like this ( though of course you would not generate this HTML before the HTML document as here! )

    <div class="result">
        <div>Reading Score: 47</div>
        <div>Listening Score: 1</div>
        <div>Speaking Score: 2</div>
        <div>Writing Score: 66</div>
        <div>Test Date: 2018-11-14</div>
    </div><div class="result">
        <div>Reading Score: 78</div>
        <div>Listening Score: 23</div>
        <div>Speaking Score: 0</div>
        <div>Writing Score: 45</div>
        <div>Test Date: 2022-07-5</div>
    </div><div class="result">
        <div>Reading Score: 34</div>
        <div>Listening Score: 54</div>
        <div>Speaking Score: 43</div>
        <div>Writing Score: 77</div>
        <div>Test Date: 2020-05-4</div>
    </div>
    

    In the FORM above the action is set to the same page just for the example – you would not want to generate HTML output before the HTML document begins like this… The above PHP could log the results to database just as easily as echoing them to screen. The question suggests that this is the end goal so within that foreach loop you would call your database insert function (using a Stored Procedure!)

    Login or Signup to reply.
  2. As written in the comments, id’s have to be unique. Second, when posting a form only the name is relevant, as it becomes the array key for the value.

    If you want to group your inputs, so the POST array becomes

    [
      0=> [ 'r' => 10, 'l' => 6, 's' => 7, 'w' => 4 ],
      1=> [ 'r' => 3, 'l' => 9, 's' => 4, 'w' => 8 ],
    ...
    ]
    

    you have to create unique names, grouped as arrays:

    <input name="entry[0][r]" type="number">
    <input name="entry[0][s]" type="number"> 
    ....
    <input name="entry[1][r]" type="number">
    <input name="entry[1][s]" type="number"> 
    

    In your javascript add a global var entry_counter=0 and in the function addEntry() upp it every time you add an entry (it doesn’t matter if the keys have gaps after you delete an entry, it’s only to make distinct groups).

    function addEntry(){
       //create the 'entry-part' of the name, based on the counter
       const entry_id="entry["+entry_counter+"]";
    
       //create a div to group the display and make it easier to remove
       let div = document.createElement("div");
    
       //create a label (for is not needed if they are next to eachother)
       let item = document.createElement("label");
       item.innerText = "Reading Score:";
       div.appendChild(item);
    
       //create an input with unique name [entry_id][type]
       item = document.createElement("input")
       item.name = entry_id + "[r]"
       item.type = "number"
       div.appendChild(item);
    
       form.appendChild(div);
    

    The POST result in PHP then looks like above.

    I made you a (partial) fiddle, so you can see how I would have done it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search