我对PDO准备好的陈述相对较新。
我不禁觉得必须有一种更简单,更简洁的方法来执行以下操作:无论如何我将所有内容加载到数组中,然后必须将整个内容重写为一组':blah '=> $ found ['blah'] 废话。
在下面做什么是更简洁的方式?
$stmt = $db->prepare("UPDATE googleplay SET name=:name, releasedate=:releasedate, version=:version, image=:image, url=:url, rating=:rating WHERE id=:id");
$stmt->execute(array(
':id'=>$found['id'],
':name'=>$found['name'],
':releasedate'=>$found['releasedate'],
':version'=>$found['version'],
':image'=>$found['image'],
':url'=>$found['url'],
':rating'=>$found['rating']
));
答案 0 :(得分:4)
您不需要在密钥名称前加上:
,它也可以不用。所以:
$stmt->execute($found);
即使您必须这样做,也要自动执行:
$found = array_combine(array_map(function ($key) { return ":$key"; }, array_keys($found)), $found);
答案 1 :(得分:2)
在PDO文档中还有其他方法可以做到这一点,有些则不是。你可以编写一个php函数来为你做这个,使它更整洁。
同样的功能也允许使用?
来表示基础。对于许多一次性查询,它更清晰。
然而,最重要的是使用ORM(对象关系映射器),例如Doctrine或任意数量的ActiveRecord克隆(例如Laravel)。
答案 2 :(得分:0)
$allowed = array('name', 'releasedate', 'version', 'image', 'url', 'rating');
$sql = "UPDATE users SET ".pdoSet($allowed, $values, $found)." WHERE id = :id";
$stm = $dbh->prepare($sql);
$values["id"] = $found['id'];
$stm->execute($values);
其中pdoSet()
是一个从提供的数组中生成SET语句的函数(对允许的字段列表检查输入数组)
但是,最好的方法是实现另一种类型的占位符,这将使您的代码成为世界上最好的代码:
$db->query("UPDATE users SET ?u WHERE id = ?i", $found, $id);
假设$found
已经过验证(意味着不是来自用户输入,而是硬编码或过滤掉)并且$id
不是数组的一部分。
答案 3 :(得分:0)
// a closure that, given a key, returns a SET subclause for an UPDATE statement
$cl_set = function($k) {
if (!preg_match('/^[[:alnum:]_]+$/', $k))
throw new Exception('Key cannot be used as a placeholder name');
return "$k = :$k";
};
// use our closure to generate the SQL
$stmt = $db->prepare(
'UPDATE googleplay SET ' . implode(', ', array_map($cl_set, array_keys($found)))
);
// execute - this works because of the observation in @deceze's answer:
$stmt->execute($found);