Search Form with One or More (Multiple) Parameters

I've gotten the basics down, where I've created two files, the search form where a user inputs search parameters, and the results file that cranks out inputted items. For the sake of simplicity, we'll designate the search form file as search.php and the results page as results.php.

search.php

<?php
    
if (!empty($_POST['id']) && isset($_POST['id'])) {
    header("Location: ?m=search.results&id=".$_POST['id']."");
} elseif (!empty($_POST['major']) && isset($_POST['major'])) {
    header("Location: ?m=search.results&major=".$_POST['major']."");
} elseif (!empty($_POST['college']) && isset($_POST['major'])) {
    header("Location: ?m=search.results&college=".$_POST['college']."");
} elseif (!empty($_POST['name']) && isset($_POST['name'])) {
    header("Location: ?m=search.results&name=".$_POST['name']."");
} elseif (!empty($_POST['id']) && !empty($_POST['college']) && !empty($_POST['major'])
                            && isset($_POST['submit']) && !empty($_POST['name'])) {
    echo "<div class='alert alert-danger'>No students found. Please try different parameters.</div>";
}

?>


<h4>Search</h4>

<form method="POST">
    <table width="100%">

<tr><td>ID:</td><td> <input type="text" name="id" class="form-control"></textarea></td></tr>

<tr><td>Name:</td><td> <input type="text" name="name" class="form-control"></textarea></td></tr>

<tr><td>Major:</td><td><select name="major" class="form-control"><option></option><?php echo majorSelect(); ?></select></td></tr>

    <tr><td>College:</td><td><select name="college" class="form-control"><option></option><?php echo collegeSelect(); ?></select></td></tr>

<tr><td colspan="2"><input type="submit" name="submit" value="Search" class="btn btn-lrg btn-primary" style="margin-top:10px;"></td></tr>

    </table>
</form>

results.php

<!-- Begin Search Parameters -->

<?php

if (isset($_GET['id'])) {
    $students = $db->query("SELECT * FROM `user_details` a, `user` b WHERE a.uid = b.id AND a.uid = '".$_GET['id']."'");
    
    while ($student = $students->fetch()) {
        echo '
            <tr>
                <td>'.$student['uid'].'</td>
                <td>'.$student['name'].'</td>
                    <td>'.$student['major'].'</td>
                    <td>'.$student['college'].'</td>
                <td><a href="?m=profile&id='.$student['id'].'" style="display:block">View</a></td>
                
            </tr>';
    }
} elseif (isset($_GET['major'])) {
    $students = $db->query("SELECT * FROM `user_details` a, `user` b WHERE a.uid = b.id AND a.major = '".$_GET['major']."'");
        
    while ($student = $students->fetch()) {
        echo '
            <tr>
                <td>'.$student['uid'].'</td>
                <td>'.$student['name'].'</td>
                    <td>'.$student['major'].'</td>
                    <td>'.$student['college'].'</td>

                <td><a href="?m=profile&id='.$student['id'].'" style="display:block">View</a></td>
                
            </tr>';
    }
} elseif (isset($_GET['college'])) {
    $students = $db->query("SELECT * FROM `user_details` a, `user` b WHERE a.uid = b.id AND a.college = '".$_GET['college']."'");
        
    while ($student = $students->fetch()) {
        echo '
            <tr>
                <td>'.$student['uid'].'</td>
                <td>'.$student['name'].'</td>
                    <td>'.$student['major'].'</td>
                    <td>'.$student['college'].'</td>
                <td><a href="?m=profile&id='.$student['id'].'" style="display:block">View</a></td>
                
            </tr>';
    }
} elseif (isset($_GET['name'])) {
    $name = $_GET['name'];
        
    $students = $db->query("SELECT * FROM `user_details` a, `user` b WHERE a.uid = b.id AND b.name LIKE '%". $name . "%'");
        
    while ($student = $students->fetch()) {
        echo '
            <tr>
                <td>'.$student['uid'].'</td>
                <td>'.$student['name'].'</td>
                    <td>'.$student['major'].'</td>
                    <td>'.$student['college'].'</td>
                <td><a href="?m=profile&id='.$student['id'].'" style="display:block">View</a></td>
                
            </tr>';
    }
}    

So, essentially I would like to rewrite the above whereas a user can input one or more parameters, and the desired result is returned (e.g. both name and college - &name=x&college=y OR all items if need be).


Solution 1:

Build the WHERE clause dynamically. My recommended approach is to push each condition onto an array, and then use implode() to concatenate all the conditions, connecting them with AND or OR as is your preference.

$wheres = array();
$params = array();
if (!empty($_GET['id'])) {
    $wheres[] = 'a.uid = :uid';
    $params[':uid'] = $_GET['id'];
}
if (!empty($_GET['major'])) {
    $wheres[] = 'a.major = :major';
    $params[':major'] = $_GET['major'];
}
if (!empty($_GET['name'])) {
    $wheres[] = 'b.name LIKE :name';
    $params[':name'] = '%'.$_GET['name'].'%';
}
// And so on for all parameters

$sql = "SELECT * 
        FROM user_details AS a
        JOIN user AS b ON a.uid = b.id";
if (!empty($wheres)) {
    $sql .= " WHERE " . implode(' AND ', $wheres);
}
$stmt = $db->prepare($sql);
$stmt->execute($params);

Then display the results as in your original code.

while ($student = $stmt->fetch()) {
    ...
}

Solution 2:

If you aren't going to change anything in the database - you are just selecting - go ahead and use GET instead of POST. The advantage of this is that it is going to allow you to save the URL as your search string. You can also refresh the search without getting the resubmit post alert. You just want to make sure that you parameterize your values before you send them to the database. I would normally send those values through sanitize functions, such as a regex that makes sure you only have letters if you expect letters, or a numbers if you expected numbers.

On the same page (all search): (I am just going to outline this for you.)

<form action="<?= $_SERVER["REQUEST_URI"]; ?>" method="GET">
    <input name="major" value="<?= $_GET["major"]; ?>" />
    <select name="college">
        <option value="1" <?PHP if( $_GET["college"] == 1 ) echo 'selected="true"'; ?>>Business</option>
    </select>
</form>

<?PHP
if( ! empty( $_GET ) ){
    if (isset($_GET['major'])) {
       $wheres[] = 'a.major = :major';
       $params[':major'] = $_GET['major'];
    }
    if (isset($_GET['name'])) {
       $wheres[] = 'b.name LIKE :name';
       $params[':name'] = '%'.$_GET['name'].'%';
    }
    // And so on for all parameters

    $sql = "SELECT * 
        FROM user_details AS a
        JOIN user AS b ON a.uid = b.id";
    if (!empty($wheres)) {
        $sql .= " WHERE " . implode(' AND ', $wheres);
    }
    $stmt = $db->prepare($sql);
    $stmt->execute($params);
}
?>

Now you can display your data.

edit: I wrote the other half of the answer, and then he wrote the 2nd half, so I just incorporated it...

Also, the next level of sophistication in this would be to take the PHP out of the search file and to put it into another file. When you press the search button in your form, you'd use AJAX to call the PHP elements. Then the PHP file would return the results via Ajax. You could return either the HTML preformatted, or JSON and let something like JQuery display it for you.