Home > Back-end >  HTML select option is undefined in PHP (JS can read its value) - AJAX form
HTML select option is undefined in PHP (JS can read its value) - AJAX form

Time:08-06

I'm trying to make a "sort" button. When someone chooses something from a list (HTML select) it will sort items from my database on my HTML page.

// head
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
    $(function () {
        $('#sort_form').on('submit', function (e) {
            e.preventDefault();

            $.ajax({
                type: "post",
                url: 'php/file-php.php',
                data: new FormData(this),
                processData: false,
                contentType: false,
                success: function () {
                    alert($("#sort").val());
                },
                error: function () {
                }
            });
        });
    });
</script>
// HTML
<?php require "php/file-php.php"; ?>

<form method="POST" id="sort_form" action="php/file-php.php" enctype='multipart/form-data'>

  <input type="submit" id="sort_btn" value="Sort">
                    
  <select name="sort" id="sort">          
    <optgroup label="alphabetically">
      <option value="alphabet_p"> 
      A-Z
      </option>

      <option value="alphabet_rev_p">
      Z-A
      </option>
    </optgroup>

    <optgroup label="in whole portion">
      <option value="kcal_low_a">
      Kcal (to highest)
      </option>

      <option value="kcal_high_a">
      Kcal (to lowest)
      </option>
    </optgroup>
  </select>

</form>
<?php 
  recipe_list_dishes();
?>
// PHP (php/file-php.php)
<?php
    function recipe_list_dishes() {
        $con = mysqli_connect("localhost", "root", "", "cookbook");
        $sort = $_POST["sort"];
        $dish_type = "'dishes'";
        $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY name";
        
        $kcal_query = "(fat * 9   carbohydrates * 4   fiber * 2   protein * 4)";
        $carbohydrates = "carbohydrates / 10";
        $wpts_query = "(fat * 9   protein * 4) / 100";

        switch ($sort) {
            case "alphabet_p":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY name";
            break;
                
            case "alphabet_rev_p":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY name DESC";
            break;
   
            case "kcal_low_a":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY $kcal_query";
            break;
            
            case "kcal_high_a":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY $kcal_query DESC";
            break;
        }

        $res = mysqli_query($con,$sql);
        
        while($row = mysqli_fetch_assoc($res)) {
            $recipename = $row['name'];
            $fat = (int)$row['fat'];
            $carbohydrates = (int)$row['carbohydrates'];
            $fiber = (int)$row['fiber'];
            $protein = (int)$row['protein'];
            $weight = (int)$row['weight'];
            $portion = (int)$row['portion'];
            
            $kcal = ($fat * 9)   ($carbohydrates * 4)   ($fiber * 2)   ($protein * 4);
            $cp = $carbohydrates / 10; // Carbohydrate portion = 10g carbs
            $wpts = ($fat * 9   $protein * 4) / 100; // Warsaw Pump Therapy School = (fat kcal   protein kcal) / 100
            
            echo "<a href='".$recipename."'>".$recipename."</a>";
            echo "Whole:<br>";
            echo round($kcal, 1)." kcal<br>";
            echo round($cp, 1)." WW<br>";
            echo round($wpts, 1)." WBT<br>";
            echo "<br>";
            echo "<img src='uploads/".$row['image']."' class='imageaaa'>";
        }
        mysqli_close($con);
    }
?>

Note: there is more code, this is just a shortened version. When I'm trying to display elements from my database in my HTML file, there is an error

Warning
: Undefined array key "sort" in
C:\xampp\htdocs\php\file-php.php
on line
5 (line 5 = $sort = $_POST["sort"];)

I checked it in js with $("#sort").val(); and it seems to work correctly. It had worked before I used AJAX, but I'm forced to do it this way (I don't want the page to be reloaded after the button submit). Also, the form isn't sent (items are not being sorted). How can I fix it?

Edit with new code:

<script>
    $(function () {
            
        $('#sort_form').on('submit', function (e) {

            e.preventDefault();

            $.ajax({
                type: "post",
                url: 'php/file-php.php',
                data: new FormData(this),
                processData: false,
                contentType: false,
                success: function () {
                    alert($("#sort").val());
                },
                error: function () {
 
                }
            });

        });
            
    });
</script>
HTML
<form method="POST" id="sort_form" enctype='multipart/form-data'>

  <input type="submit" id="sort_btn" value="Sort">
                    
  <select name="sort" id="sort">          
    <optgroup label="alphabetically">
      <option value="alphabet_p"> 
      A-Z
      </option>

      <option value="alphabet_rev_p">
      Z-A
      </option>
    </optgroup>

    <optgroup label="in whole portion">
      <option value="kcal_low_a">
      Kcal (to highest)
      </option>

      <option value="kcal_high_a">
      Kcal (to lowest)
      </option>
    </optgroup>
  </select>

</form>
<?php require "php/display.php" ?> // it displays nothing without it
<?PHP 
  recipe_list_dishes();
?>
                    
<?PHP 
  recipe_list_desserts();
?>
                 
<?PHP 
  recipe_list_snacks();
?>
//php (php/file-php.php)
<?php
        $con = mysqli_connect("localhost", "root", "", "cookbook");
        $sort = $_POST["sort"];
        $dish_type = "'dania'";

        $kcal_query = "(fat * 9   carbohydrates * 4   fiber * 2   protein * 4)";
        $carbohydrates = "carbohydrates / 10";
        $wpts_query = "(fat * 9   protein * 4) / 100";

        switch ($sort) {
            case "alphabet_p":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY name";
            break;
                
            case "alphabet_rev_p":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY name DESC";
            break;
 
            case "kcal_low_a":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY $kcal_query";
            break;
            
            case "kcal_high_a":
                $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY $kcal_query DESC";
            break;
        }

echo $sort." hello";
       
mysqli_close($con);

?>      
// PHP (php/display.php)
<?php
require "php/file-php.php"; 
    function recipe_list_dishes() {
        $con = mysqli_connect("localhost", "root", "", "cookbook");
        $dish_type = "'dishes'";
        $sql = "SELECT * FROM product WHERE type = $dish_type ORDER BY name";

        $res = mysqli_query($con,$sql);
        
        while($row = mysqli_fetch_assoc($res)) {
            $recipename = $row['name'];
            $fat = (int)$row['fat'];
            $carbohydrates = (int)$row['carbohydrates'];
            $fiber = (int)$row['fiber'];
            $protein = (int)$row['protein'];
            $weight = (int)$row['weight'];
            $portion = (int)$row['portion'];
            
            $kcal = ($fat * 9)   ($carbohydrates * 4)   ($fiber * 2)   ($protein * 4);
            $cp = $carbohydrates / 10; // Carbohydrate portion = 10g carbs
            $wpts = ($fat * 9   $protein * 4) / 100; // Warsaw Pump Therapy School = (fat kcal   protein kcal) / 100
            
            echo "<a href='".$recipename."'>".$recipename."</a>";
            echo "Whole:<br>";
            echo round($kcal, 1)." kcal<br>";
            echo round($cp, 1)." WW<br>";
            echo round($wpts, 1)." WBT<br>";
            echo "<img src='uploads/".$row['image']."' class='imageaaa'>";

        }
        mysqli_close($con);
    }

?>

There can be some mistakes because I have to change some names to English. As you can see I have more functions to display the data, they have a different $dish_type value.

CodePudding user response:

In the file-php.php file you need to set an isset condition to get the data posted via ajax on this file.

Remove the function "recipe_list_dishes" and put the code inside the isset() condition.

Since you are sending the data in the variable "data" from the AJAX as shown below:

data: new FormData(this),

Thus in the file-php.php file you need to start with the condition stated below and the 'data' key contains the posted data not 'sort':

if(isset($_POST['data'])){
   $sort=$_POST['data'];
   print_r($sort); 
   //to see what exactly are you getting.
   //you must be getting the values : alphabet_p or alphabet_rev_p or kcal_low_a or kcal_high_a
}

Another thing that is not according to the standards that I found at the end of your file-php.php is:

echo "<a href='".$recipename."'>".$recipename."</a>";
            echo "Whole:<br>";
            echo round($kcal, 1)." kcal<br>";
            echo round($cp, 1)." WW<br>";
            echo round($wpts, 1)." WBT<br>";
            echo "<br>";
            echo "<img src='uploads/".$row['image']."' class='imageaaa'>";

REPLACE IT WITH THE CODE PROVIDED BELOW:

$response = "<a href='".$recipename."'>".$recipename."</a>Whole:<be>";
$response .= round($kcal, 1)." kcal<be>";
$response .= round($cp, 1)." WW<be>";
$response .= echo round($wpts, 1)." WBT<be>";
$response .= "<br>";
$response .= "<img src='uploads/".$row['image']."' class='imageaaa'>";

outside the while loop you can

echo $response;

This $response contains some HTML which will be returned to the AJAX success function as a response from the PHP file

CodePudding user response:

Gathering the data

You have this JS code for submit:

    $(function () {
        $('#sort_form').on('submit', function (e) {
            e.preventDefault();

            $.ajax({
                type: "post",
                url: 'php/file-php.php',
                data: new FormData(this),
                processData: false,
                contentType: false,
                success: function () {
                    alert($("#sort").val());
                },
                error: function () {
                }
            });
        });
    });

Here you instantiate FormData, passing this, that is, the element whose event is being processed. It would not hurt to use a debugger and check the result of FormData instantiation, see whether your sort is indeed loaded. Of course, this should be the case, given the fact that your select tag has the name of sort, but it is not necessarily the case.

Check the request data

When you test this in the browser, looking for $("#sort").val() actually checks whether the element with the id of sort has a (proper) value. However, if this element has a proper value, that does not mean that it is actually being sent to the server via the request. You only assume that if the value is proper, then it is being sent.

To actually test this, you will need to open the Dev Tools of your browser, navigate to the Network tab and see the requests being sent. When this preparement is done, you can submit your form via AJAX (click on the button) and see a new line in the requests grid of the Network tab of the Dev Tools of your browser. See what is being sent in the payload tab if you have such a tab or wherever your browser shows the request parameters. If you see the sort parameter there with proper value, THEN you know that your sort value was successfully sent to the server.

Separate the initial page load from the submit of your form

As it is, your code calls recipe_list_dishes(); just after your form is defined. So, recipe_list_dishes() is called before you submitted the form and at this stage, you do not have anything resembling a $_POST["sort"] at the server-side, which gives you the warning you have mentioned in your question.

You will need to avoid calling this function just after your HTML and, instead, make sure that it's properly reached when you actually submit your form. So, first your page is loaded, then, you submit your form. Your code that runs when the page initially loads assumes that a sort was already submitted, which of course does not happen when you load your page, it only happens when you actually submit the form.

Default your sort value

You have this code

$sort = $_POST["sort"];

which assumes that whenever this code runs, you have a posted sort. Don't assume that. Instead, default it to some value, so, if for whatever reason sort is not properly defined, the page and the form would still be operational (for example if you or one of your colleagues mistakenly remove the sort select, or rename it or whatever, then, instead of having errors, the sort would fail gracefully). So, let's use a default if needed:

$sort = isset($_POST["sort"]) ? $sort = $_POST["sort"] : "alphabet_p";

SQL injection

Finally, you do not protect your code. You should use parameterized queries to sanitize and protect against SQL injection. I admit that as it stands, your code looks to be safe, but it's only an accident, because the one parameter that you receive is not actually injected into your SQL code, but that could change anytime, so I strongly advise you to look into SQL injection, sanitize your code and, if you will get parameters that are actually injected into your query, if you apply this good practice, then it is unlikely that you would end up with a vulnerability. While, with your current code, which ignores this danger after some evolution can easily become vulnerable.

  • Related