{已解决 - 请参阅解决方案}
{PROBELM:}我有一个PHP页面,用户可以通过输入名称,从下拉菜单中选择一个郊区或从单选按钮中选择一个等级来搜索公园。我有一个PHP文件来执行数据库中公园的mySQL搜索,该搜索匹配用户对搜索表单的输入。 用户可以在不输入名称或选择郊区的情况下进行搜索,如果将这些参数留空,我需要我的SQL查询来忽略这些参数。 请注意,始终会输入评级。从下拉菜单中选择郊区,因此可以使用'='将其与表中的郊区进行比较。由于该名称是由用户输入的,我想使用“LIKE”将其与表格中的名称进行比较。
仅使用评级作为参数的查询有效:
$query = "SELECT DISTINCT * FROM parks,reviews WHERE parks.id = reviews.park_id AND reviews.Rating >= :Rating;
但是当我尝试将郊区和名称引入搜索时,我遇到了问题。
问题#1:将LIKE和%用于参数而不是文字字符串。
我试过了
parks.Name LIKE :Name
parks.Name LIKE '%'+:Name'%'
parks.Name LIKE '%'.:Name'%'
并且每个用$或@替换:在名称之前,它们都不起作用。
问题#2:如果没有输入,则SQL忽略名称和郊区的过滤器。 我试过(仅以郊区为例):
$query = "SELECT DISTINCT * FROM parks,reviews WHERE parks.id = reviews.park_id AND (parks.Suburb = :Suburb OR :Suburb IS NULL)";`
和
$query = "SELECT DISTINCT * FROM parks,reviews WHERE parks.id = reviews.park_id AND (parks.Suburb = :Suburb OR :Suburb = NULL)";
并为名称尝试了相同的想法。
// Collect input values
$Suburb = $_POST['Suburb'];
$Name = $_POST['Name'];
$Rating = $_POST['Rating'];
// Create and prepare query
$query = "SELECT DISTINCT * FROM parks,reviews WHERE parks.id = reviews.park_id AND reviews.Rating >= :Rating AND parks.Name LIKE :Name AND parks.Suburb = :Suburb";
// Prepare the statement to prevent SQL injections
$stmt = $database->prepare($query);
// Bind parameters
$stmt->bindParam(':Suburb', $Suburb);
$stmt->bindParam(':Name', $Name);
$stmt->bindParam(':Rating', $Rating);
// Execute the query
$stmt->execute();
{SOLUTION:} 我必须根据每个参数是否有值动态创建查询,并直接将'%'附加到名称字符串以使用LIKE。
try {
//Create WHERE part of query
$Where = "WHERE ";
//If filter value entered, collect value and add to WHERE statement
if($_POST['Rating'] != 'ANY'){
$Rating = $_POST['Rating'];
if($Where != 'WHERE '){
$Where .= "AND ";
}
$Where .= "parks.id = reviews.park_id AND reviews.Rating >= :Rating ";
}
if($_POST['Suburb'] != 'ALL'){
$Suburb = $_POST['Suburb'];
if($Where != 'WHERE '){
$Where .= "AND ";
}
$Where .= "parks.Suburb = :Suburb ";
}
if ($_POST['Name'] != ''){
$Name = "%";
$Name .= $_POST['Name'];
$Name .= "%";
if($Where != 'WHERE '){
$Where .= "AND ";
}
$Where .= " parks.Name LIKE :Name ";
}
// Create query with WHERE statement
$query = "SELECT DISTINCT * FROM parks ";
if($_POST['Rating'] != 'ANY'){
$query .= ",reviews ";
}
if($Where != 'WHERE '){
$query .= $Where;
}
// Prepare the statement to prevent SQL injections
$stmt = $database->prepare($query);
// Bind valid parameters
if($_POST['Suburb'] != 'ALL'){
$stmt->bindParam(':Suburb', $Suburb);
}
if ($_POST['Name'] != ''){
$stmt->bindParam(':Name', $Name);
}
if($_POST['Rating'] != 'ANY'){
$stmt->bindParam(':Rating', $Rating);
}
// Execute the query
$stmt->execute();
if ($stmt->rowCount() > 0) {
//Save results
$_SESSION['results'] = $stmt->fetchAll();
}
else{
$_SESSION['results'] = "NONE";
}
}
答案 0 :(得分:1)
使用isset
函数检查每个提交的参数。然后根据它构建您的查询。
TIPS :始终使用prepare语句来防止SQL注入也使用INNER JOINS
组合两个表,最后,对于代码约定,变量始终以小写开头。在此示例中,我使用的是mysqli
,但您也可以使用PDO:
$conn = new mysqli('servername', 'username', 'password', 'dbname');
//Checking connection
if ($conn->connect_error) {
die($conn->connect_error);
}
$stmt = $conn->prepare("SELECT DISTINCT * FROM parks
INNER JOIN reviews ON park.id=reviews.id
AND (parks.Suburb = ? OR parks.Suburb = NULL)");
$stmt->bind_param("s", $suburb);
if(isset($_POST)){
$suburb = NULL;
if(isset($_POST['Suburb'])){
$suburb = $_POST['Suburb'];
} //etc....
$stmt->execute();