Several other answers mention the risk of embedding SQL code, and the couple explicitly mentions the use of prepared statements, but none of them explicitly show how you could do this, which can be a big request for a beginner.
My current preferred method of solving this problem is using the MySQL "IF" statement to check if the parameter in question is empty / empty (depending on type). If it is empty, it compares the field value with itself ( WHERE field1=field1 always returns true ). If the parameter is not empty / zero / zero, the field value is compared with the parameter.
So, here is an example using prepared MySQLi statements (assuming $ mysqli is an already created mysqli object):
$sql = "SELECT * FROM moth_sightings WHERE user_id = ? AND location = IF(? = '', location, ?) AND english_name = ?"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('ssss', $username, $value1, $value1, $value2); $stmt->execute();
(I assume $value2 is a string based on the field name, despite the lack of quotes in the OP example in SQL.)
There is no way in MySQLi to bind the same parameter to multiple placeholders inside a statement, so we must explicitly bind $value1 twice. The advantage MySQLi has in this case is that the parameter is explicitly typed - if we pass $value1 as a string, we know that we need to compare it with an empty string. '' If $value1 were an integer value, we could explicitly declare this as follows:
$stmt->bind_param('siis', $username, $value1, $value1, $value2);
and compare it to 0 .
Here is an example PDO using named parameters, because I think they lead to a much more readable code with a lower count:
$sql = "SELECT * FROM moth_sightings WHERE user_id = :user_id AND location = IF(:location_id = '', location, :location_id) AND english_name = :name"; $stmt = $pdo->prepare($sql); $params = [ ':user_id' => $username, ':location_id' => $value1, ':name' => $value2 ]; $stmt->execute($params);
Note that with named PDO parameters, we can refer to :location_id several times in the request, binding it only once.