我把头发拉过来 - 希望这是一个容易的疏忽。
我打算用jQuery AJAX函数向这个PHP文件发送一堆变量。我写了这一节,将所有$ _POST变量分配给php变量:
foreach($_POST as $key => $value){
$$key = $value;
}
它似乎正在起作用,因为我可以像这样操纵变量:
echo 'name: ' . $name . '<br>';
echo 'main_pic: ' . $main_pic . '<br>';
echo 'product_pic: ' . $product_pic . '<br>';
echo 'more_pic: ' . $more_pic . '<br>';
echo 'paypal_code: ' . $paypal_code . '<br>';
echo 'category_id: ' . $category_id . '<br>';
echo 'price: ' . $price . '<br>';
echo 'description: ' . $description . '<br>';
echo 'product_color: ' . $product_color . '<br>';
echo 'design_color: ' . $design_color;
所以现在我有那些,我想把它们插入我的表 -
$qry = $pdo->prepare("INSERT INTO inventory (name, main_pic, product_pic, more_pic, paypal_code, category_id, price, description, product_color, design_color)
VALUES (:name, :main_pic, :product_pic, :more_pic, :paypal_code, :category_id, :price, :description, :product_color, :design_color)");
$qry-> bindParam(':name', $name);
$qry-> bindParam(':main_pic', $main_pic);
$qry-> bindParam(':product_pic', $product_pic);
$qry-> bindParam(':more_pic', $more_pic);
$qry-> bindParam(':paypal_code', $paypal_code);
$qry-> bindParam(':category_id', $category_id);
$qry-> bindParam(':price', $price);
$qry-> bindParam(':description', $description);
$qry-> bindParam(':product_color', $product_color);
$qry-> bindParam(':design_color', $design_color);
$qry-> execute();
这不会运行 - 我不确定记录错误的最佳方法,以了解原因。如果我手动分配变量并注释掉我之前的$ _POST shenanigans,一切似乎都有效,INSERT运行正常。
任何线索?我想这可能是因为数据库期望某种变量类型,但我想我已经充分探索过了。
任何人都知道手动分配变量的任何原因会起作用但是从$ _POST中抓取它们会不会?
编辑:按照这些建议,我收到了一条错误消息 SQLSTATE [23000]:完整性约束违规:1062密钥1的重复条目“0”
好吧,所以当我尝试这个插入时,我没有分配一个唯一的主键 - 我假设PDO会处理它。处理分配唯一主键的最佳方法是什么?我想避免让用户手动分配它。
答案 0 :(得分:3)
这不是答案,但它看起来比评论更好。你为什么要这样做:
foreach($_POST as $key => $value){
$$key = $value;
}
这是重复注册全局(有点)。使用上面的代码,您可以轻松覆盖意外结果的局部变量,甚至更糟糕的是引入安全漏洞。
如果我发布$_POST['is_admin'] = 1
或类似内容怎么办?无论哪种方式,我认为你明白了。你刚刚做的很糟糕,可能很危险。
答案 1 :(得分:2)
像@PeeHaa一样,这不是答案,而是扩展我对他的评论;删除伪寄存器全局功能:选择一个白名单字段,并将名称与发布的名称进行协调。
$fields = ['name', 'age', 'sex'];
$query = $pdo->prepare(sprintf('INSERT INTO `table` (%s) VALUES (%s)',
implode(',', $fields),
implode(',', array_map(function($field) {
return ":{$field}";
}, $fields))));
foreach($fields as $field) {
$query->bind(":{$field}", $_POST[$field]);
}
$query->execute();
显然,这需要更多验证,空()检查等,但你明白了。此外,您可以使用回调查找添加更多验证/清理:
$sanitizers = [
'sex' => function($value) {
$value = strtolower($value);
return in_array($value, ['male', 'female', 'unknown'])
? $value : 'unknown';
},
];
foreach($sanitizers as $field => $sanitizer) {
if (isset($_POST[$field])) {
$_POST[$field] = $sanitizer($_POST[$field]);
}
}
如果帖子中包含“无性别”的“性别”,则会获得“未知”。
更完整的例子:
// whitelist keys and sanitizer values
$fields = [
// limit to 255
'name' => function($value) {
return substr($value, 0, 255);
},
// you can't be that old
'age' => function($value) {
return min(max((int) $value, 0), 100);
},
// starfish need not apply
'sex' => function($value) {
$value = strtolower($value);
return in_array($value, ['male', 'female', 'unknown'])
? $value : 'unknown';
},
];
// build ye' old query
$query = $pdo->prepare(sprintf('INSERT INTO `table` (%s) VALUES (%s)',
implode(',', array_keys($fields)),
implode(',', array_map(function($fields){
return ":${$field}";
}, array_keys($fields)))));
// loop dee doop to sanitize and bind
foreach ($fields as $key => $sanitizer) {
if (is_callable($sanitizer)) {
$query->bind(":{$field}", $sanitizer($_POST[$field]));
continue;
}
$query->bind(":{$field}", $_POST[$field]);
}
// fire the cannons!
$query->execute();
答案 2 :(得分:1)
清空数据库表并查看它是否有效...可能你在db表中有一个主键,你试图覆盖它。
使用EXPLAIN inventory
答案 3 :(得分:1)
如果需要,您可以拥有自动增量主键。假设你使用mysql: http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
答案 4 :(得分:1)
OP说: 好吧,所以当我尝试时,我没有分配一个唯一的主键 这个插入 - 我假设PDO会处理这个问题。 处理分配唯一主键的最佳方法是什么?我&#39; d 喜欢避免让用户手动分配它。
只是解决这一部分或您的问题 - 您只需使用不带引号的0
insert into table (id, name) values (0, 'Bob');
但正如你所说,如果它是一个正确自动递增的id,你不应该这样做。
在旧版本的Mysql(&lt; 5)中,你可以使用一个空字符串,当5.0出现时它会爆炸,以防万一有人读到这个字符串与之前未记录的功能相违背。