我正在尝试针对我正在上课的网页项目构建后端解决方案。该课程没有涉及后端编码,因此我必须自己学习所有内容。我想了解如何利用准备好的语句并加入下面的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);