Php 准备语句,使用int表字段进行插入
我正在做一个学习OOP的个人项目。我创建这个通用方法是为了对表进行插入,但我不能Php 准备语句,使用int表字段进行插入,php,pdo,insert,prepared-statement,Php,Pdo,Insert,Prepared Statement,我正在做一个学习OOP的个人项目。我创建这个通用方法是为了对表进行插入,但我不能$dbAttributes是表中没有id的字段列表。我传递一个对象实例,例如,设置了属性的产品,如类别id、产品名称、价格。当我尝试使用foreach循环绑定值时,问题就出现了 我发现错误: SQLSTATE[HY000]:一般错误:1366不正确的整数值 从占位符中删除单引号后,我得到: SQLSTATE[42000]:语法错误或访问冲突:1064 公共静态函数创建($obj){ 全球$db; $db->setAt
$dbAttributes
是表中没有id的字段列表。我传递一个对象实例,例如,设置了属性的产品,如类别id、产品名称、价格。当我尝试使用foreach循环绑定值时,问题就出现了
我发现错误:
SQLSTATE[HY000]:一般错误:1366不正确的整数值
从占位符中删除单引号后,我得到:
SQLSTATE[42000]:语法错误或访问冲突:1064
公共静态函数创建($obj){
全球$db;
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_异常);
$dbAttributes=$obj->db_字段;
$colonValues=array();
对于($i=0;$iprepare($sql);
foreach($k=>$value的冒号值){
$rs=$obj->$dbAttributes[$k];
//如果($k!=0){
$stmt->bindParam($value,$rs);
echo gettype($rs)。“.$rs.”
“;//}
}
变量转储($sql);
$numrowsimpacted=$db->exec($sql);
}捕获(例外$ex){
echo$ex->getMessage();
}
}
正如您所看到的,我正在尝试动态创建SQL并动态绑定值。我尝试了所有方法,还阅读了关于使用表名的反勾号的论坛,但没有解决问题。您准备了语句,但没有执行准备好的语句。您
exec($SQL)
作为未准备好的语句。此方法不支持查询参数,它逐字执行SQL。因此,当MySQL需要整数文本并找到:columnname
时,它会抱怨,这并不奇怪
$numRowsAffected = $db->exec($sql);
这应该是:
$stmt->execute();
$numRowsAffected = $stmt->rowCount();
参数占位符不能放在SQL中的引号内
此外,您不必使用bindValue(),只需传递一个数组以执行()
下面是编写函数的一种更简单的方法:
public static function create($obj) {
global $db;
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$dbAttributes = $obj->db_fields;
$columns = array_map(function ($col) { return "`" . $col . "`"; },
array_values($dbAttributes));
$paramPlaceholders = array_map(function ($col) { return ":" . $col; },
array_values($dbAttributes));
$paramValues = array_intersect_key(get_object_vars($obj), array_flip($dbAttributes));
$sql ="INSERT INTO `".$obj::$tableName."` (".implode(",",$columns).")"
. " VALUES (".implode(",",$paramPlaceholders).")";
try {
$stmt = $db->prepare($sql);
$stmt->execute($paramValues);
$numRowsAffected = $stmt->rowCount();
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
我试着用你的建议来修复我的代码,效果很好。作为对任何人的提醒,当我用上面的代码执行bindParam时,它会将所有内容都更改为字符串,所以我使用了bindValue,并按照你的建议使用了execute()。你的方法简短明了。我在一篇教程exec()中读到了一个问题当我们插入、更新或删除时非常理想,因为它返回受影响的行数。从您的回答中,我应该只对准备好的语句使用execute()而不是exec()。您是这么说的吗?您还添加了backtick;是因为Placeholder名称与列名匹配吗?exec()不支持预处理语句,因此如果使用exec(),则不能有参数。我在表名和列名周围添加了回标记,以防它们与SQL保留字匹配。
public static function create($obj) {
global $db;
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$dbAttributes = $obj->db_fields;
$columns = array_map(function ($col) { return "`" . $col . "`"; },
array_values($dbAttributes));
$paramPlaceholders = array_map(function ($col) { return ":" . $col; },
array_values($dbAttributes));
$paramValues = array_intersect_key(get_object_vars($obj), array_flip($dbAttributes));
$sql ="INSERT INTO `".$obj::$tableName."` (".implode(",",$columns).")"
. " VALUES (".implode(",",$paramPlaceholders).")";
try {
$stmt = $db->prepare($sql);
$stmt->execute($paramValues);
$numRowsAffected = $stmt->rowCount();
} catch (Exception $ex) {
echo $ex->getMessage();
}
}