-2

Scenario:

I am populating a dropdown menu with data from MySQL database. Upon clicking submit button, script should take the user to the results page and show data based on their selection.

Problem:

User selection is not able to POST to next page for the query. When I hard code an option in that matches one of the dropdown options, the query works fine.

-- This is the dropdown --

<div class = "servicelinesearchbox">
   <div class="servicelinesearchbar">
        <form class="form-inline" method="post" action="search_by_service_line.php">
              <select name="service_lines" id ="service_lines" form="service_line_form">
                  <option value = "">---SELECT A SERVICE LINE---</option>

               // THIS OPTION ADDED FOR TESTING, DOES WORK AND POPULATE DATA ON NEXT PAGE --
                  <option value = "Architectural">Architectural</option>
                  <?php
                  $sql = "SELECT service_lines FROM service_lines ORDER BY service_lines";
                  $db = mysqli_query($conn, $sql);
                  while ( $d=mysqli_fetch_assoc($db)) {
                  echo "<option value='{".$d['service_lines']."}'>".$d['service_lines']."</option>";
                  }
                  ?>
               </select>  
               <button type="submit" name="save" class="btn btn-primary">SEARCH</button>
       </form>
   </div>
</div>

-- This is the part of the results page that uses POST data to run the query --

<?php

include "config.php";

if (isset($_POST["save"])> 0) {
    $service_lines = htmlspecialchars($_POST['service_lines']);
    $sql = "SELECT * FROM subconsultants WHERE service_lines LIKE '$service_lines'";
    $result = mysqli_query($conn, $sql);
}
?>
zth_codes
  • 1
  • 2
  • 1
    Your script is vulnerable to [SQL Injection Attack](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php). Even if [you are escaping variables, its not safe](https://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string%5D)! You should always use [prepared statements and parameterized queries](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) in either MYSQLI or PDO instead of concatenating variables into the query. – Barmar Apr 17 '23 at 17:30
  • 1
    *"User selection is not able to POST to next page for the query."* - Can you clarify the specific debugging observations you're making and specifically what is failing? Is the form not posting **at all**? Is it posting, but not with the value(s) you expect? Is it posting the expected value(s) but something isn't working as expected in the server-side code? Something else? – David Apr 17 '23 at 17:30
  • 1
    Do you see the options in the menu? If not, do you see them when you do `View Source`? – Barmar Apr 17 '23 at 17:31
  • Why are you putting `{}` around the values? `value='{".$d['service_lines']."}'` – Barmar Apr 17 '23 at 17:32
  • You don't have those curly braces in `value = "Architectural"`, so I think that's why it works and the dynamic ones don't. Get rid of them. – Barmar Apr 17 '23 at 17:35
  • You should also use `=` rather than `LIKE` when looking up the consultants, since it doesn't have any wildcards. – Barmar Apr 17 '23 at 17:37
  • @Barmar Removing the curly braces worked. Also changed LIKE back to =. I originally had it like that but changed it to see if it made a difference. Also, could you give me an example of how to use prepared statements and parameterized queries instead of concatenation please? I rarely if ever do front-end work – zth_codes Apr 17 '23 at 17:42
  • The examples are in the link in my comment. – Barmar Apr 17 '23 at 18:52

1 Answers1

0

Added more information as requested by @zth_codes

in line:

echo "<option value='{".$d['service_lines']."}'>".$d['service_lines']."</option>";

curly braces are no needed: remove them

in line:

$sql = "SELECT * FROM subconsultants WHERE service_lines LIKE '$service_lines'";

must be added % to let the LIKE operator work: LIKE '%$service_lines%'

and using paramters instead of string concatenation will prevent SQL injections

Example of using prepared statements and parameters in the query and further recommendations

A possible example for prepared statement with parameters can be this:

<?php

include 'config.php';

if (isset($_POST['save'])) {
    
    $sql = 'SELECT * FROM subconsultants WHERE service_lines = ?';
    
    $stmt = mysqli_stmt_init($conn);
    mysqli_stmt_prepare($stmt, $sql);
    mysqli_stmt_bind_param($stmt, 's', $_POST['service_lines']);
    mysqli_stmt_execute($stmt);
    
    $result = mysqli_stmt_get_result($stmt);
    $row = $result->fetch_array();
}

It's a bit more verbose but avoids SQL injection.

I also replaced the LIKE operator with the = operator in the query, since it doesn't seem to me that partial searches are needed: this way you will also benefit from any indexes on the search column

Another tip: don't use double quotes in strings unless necessary: ​​double quotes always make the string go through special character handling and variable expansion.

Finally, I advise against closing the PHP code with the ?> tag if there are no further lines of HTML in the PHP file: any empty and invisible lines in the code after the ?> tag are interpreted as (unwanted) HTML lines

Pippo
  • 2,173
  • 2
  • 3
  • 16
  • Removing the curly braces solved the problem. Could you give me an example of how to use parameters instead of string concatenation please? I'm very new to PHP, I mainly do back-end coding but had to create this tool for work as I'm the only developer currently. – zth_codes Apr 17 '23 at 17:39
  • @zth_codes I've added an example and further recommendations in my answer as requested – Pippo Apr 18 '23 at 06:47
  • thank you very much. Also, I just went to keep working on this today and now it no longer works? It is telling me undefined array key for this line: $service_lines = htmlspecialchars($_POST['service_lines']); But yesterday it worked? – zth_codes Apr 19 '23 at 14:36
  • @zth_codes - Have you changed the name of *select input*? - Did you add at least one option to your *select input*? - Also remove *form* attribute from *select input*. (If you use prepared statements with parameters you don't need anymore to apply htmlspecialchars() to your input) – Pippo Apr 19 '23 at 15:00
  • I removed the form attribute and it fixed it, thank you so much for your help! – zth_codes Apr 19 '23 at 15:13
  • @zth_codes glad to have been of help. – Pippo Apr 19 '23 at 15:14