这对我来说至少是一个稍微复杂的话题,我正在创建一个网站,要求能够更新已输入并保存到数据库的信息。我已经设法使用单个属性有效地工作,但我希望修改它以便能够更改任何选定的属性。将从名为update.php
的页面的下面代码中的下拉菜单中选择所选属性<form action="updatejob.php" method="POST">
<label for="jobs_id">Job ID:</label><input type="text" name="jobs_id" />
<select name="updatecategory">
<option value="title">Title</option>
<option value="category">Category</option>
<option value="salary">Salary</option>
<option value="location">Location</option>
<option value="description">Description</option>
</select>
<label for="newcontent">Updated Information: </label><input type="text" name="newcontent" />
<input type="submit" value="Submit" name="submit"/>
</form>
我试图编写的查询位于名为updatejob.php的文件中:
if(isset($_POST['jobs_id'])){
$updatetitle= $pdo->prepare('UPDATE jobs SET :updatecategory = :newcontent WHERE jobs_id = :jobs_id');
unset($_POST['submit']);
$updatetitle->execute($_POST);
header("Location:admin.php");
}
正如我上面提到的,当我将它设置为一个不在选择框中的特定属性时,这可以正常工作。以前我设置它,所以用户只能使用文本框编辑记录的标题。说实话,我甚至不确定这是否可能,或者我是否特别接近正确的方式,所以所有的帮助都表示赞赏!
答案 0 :(得分:0)
有趣。 According to the PDO docs,您不能绑定列名等标识符,因此您需要在动态查询中使用一些变体,这通常会让您注入攻击攻击。我们想到的最强大的解决方案是使用查找表将<select>
值索引到列名称,这些值用于填充空白&#34;在准备好的声明中。
column_lookup
+----------+----------+
| selval | colname |
+==========+==========+
| title | title |
| category | category |
| location | location |
| etc. | etc. |
然后你会做类似
的事情$colsql = "SELECT colname FROM column_lookup WHERE selval = :selval"
$colstmt = $dbh->prepare($colsql);
$res = $colstmt->execute(array(':selval' => $_POST['updatecategory']));
$updsql = "UPDATE jobs
SET " . $res->fetchColumn(0) . " = :newcontent
WHERE jobs_id = :jobs_id";
$updstmt = $dbh->prepare($updsql);
$updstmt->bindValue(':newcontent', $_POST['newcontent'], PDO::PARAM_STR);
$updstmt->bindValue(':jobs_id', $_POST['jobs_id'], PDO::PARAM_whatever);
$updstmt->execute;
这样可以通过准备好的语句清理所有输入,同时仍然动态生成UPDATE
查询。
我的习惯是将错误处理留给读者练习。特别是,我省略了任何验证jobs_id
的数据类型的尝试。
答案 1 :(得分:0)
我在你当前的方法中看到了一个拦截器。除了不清理您的数据。您正在尝试参数化列。 prepare语句的工作方式是发送/缓存查询计划并分别发送参数。因此,您无法绑定部分查询计划,因为它事先已发送/缓存。
为语句调用PDO :: prepare()和PDOStatement :: execute() 将使用不同的参数值多次发出 通过允许驱动程序优化应用程序的性能 协商客户端和/或服务器端缓存查询计划和 元信息,并有助于防止SQL注入攻击 无需手动引用参数。
这并不意味着你不能拥有查询计划的动态方面,你就是不能让它们受到约束。
动态查询计划示例。
<?php
$whiteListedColumns = array(
"valid", "schema", "etc"
);
$updateCategory = in_array($_POST["updatecategory"], $whiteListedColumns) ? $updateCategory : null;
if($updateCategory) {
//Sanitize Here
//Its really important to understand what the filter reference docs.
//You can skip for now.
$params = array(
"newcontent" => filter_var($_POST["newcontent"], FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES),
"jobs_id" => (int) $_POST["jobs_id"],
);
//Notice I simply concatenated the query string (didn't bind)
$sql = "UPDATE jobs
SET {$updateCategory} = :newcontent
WHERE jobs_id = :jobs_id";
$stmt = $pdo->prepare($sql);
$stmt->execute($params); //This is what is binding the params
//redirect
header("Location:admin.php");
exit();
} else {
//Invalid Column
//Throw
}
除了拥有静态白名单之外,您还可以发出另一个查询来读取数据库架构。
<强>建议:强> 使用像Doctrine这样的DBAL。它将为您完成大部分基础工作。
希望这有用!