关于准备好的声明和联合的建议



我正试图为我正在学习的一个类构建一个网页项目的后端解决方案。这门课没有涉及任何关于后端编码的内容,所以我必须自己学习所有内容。我想了解如何在下面的PHP代码中使用准备好的语句和联接。我的数据库中有三个表,但我只想从其中一个表中返回数据,有时只需要引用另外两个表来进行搜索。

该代码目前按预期工作,但易受sql注入的影响。我从用户那里得到了三个表单输入:文本输入($_POST["spell_name"](、选择元素($_POST["classList"](和一些复选框($_POST["school"](。当复选框发送一个空数组(没有选中任何复选框(并且select元素发送默认值"all"时,它仍然需要工作。

$sql = "SELECT * FROM dnd5_spells WHERE ";
if($_POST["classList"] != "all"){
$sql .= "spell_id= ANY(SELECT spell_id FROM dnd5_class_spells WHERE class_id = ANY(SELECT class_id FROM dnd5_classes WHERE class_name='{$_POST["classList"]}')) AND";
};
$sql .= " spell_name LIKE '%{$_POST["spell_name"]}%'";
if(!empty($_POST["school"])){
$sql .= " AND (";
$spellschools = $_POST["school"];
$valueLength = count($spellschools);
for ($x = 0; $x < $valueLength; $x++) {
if ($x>0) {
$sql.= " OR";
};
$sql .= " spell_type" . " LIKE" . " '%" . $spellschools[$x] . "%'";
};
$sql .= ")";
};
$result = mysqli_query($conn, $sql);

当我可以接收到所有或没有可能的输入值,并且我不知道我提前得到了什么(在我的情况下,发送表单数据为空会返回整个表,这很好(时,我该如何做出准备好的声明?当数组可以为空或有多个值时,我可以将数组迭代为准备好的语句吗?当不需要sql查询的部分时,我是否应该考虑包含该部分?

此外,我知道我对ANY的使用可能会被JOIN取代,但我无法理解它,它对我来说没有解决准备好的语句问题那么重要。

这是我找到的解决方案。我需要使用PDO,然后根据准备好的语句构建语句,将?放在我想要输入数据的地方,同时构建一个具有相应数据值的数组。我怀疑它是否完美,但它和我最初的代码一样好用,而且不太容易受到SQL注入的影响。

$sql = "SELECT * FROM dnd5_spells WHERE ";
$parameters = [];
if($_POST["classList"] != "all"){
$sql .= "spell_id= ANY(SELECT spell_id FROM dnd5_class_spells WHERE class_id = ANY(SELECT class_id FROM dnd5_classes WHERE class_name= ?)) AND";
$parameters[] = $_POST["classList"];
};
$sql .= " spell_name LIKE ?";
$parameters[]= "%" . $_POST["spell_name"] . "%";
if(!empty($_POST["school"])){
$sql .= " AND (";
$spellschools = $_POST["school"];
$valueLength = count($spellschools);
for ($x =0; $x < $valueLength; $x++){
if ($x>0){
$sql.= " OR";
};
$sql.= " spell_type LIKE ?";
$parameters[] ="%" . $spellschools[$x] . "%";
};
$sql .= ")";
};
//bind the peramaters into the prepared statment
$stmt = $conn->prepare($sql);
$stmt->execute($parameters);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

最新更新