Php PDO INSERT不使用$\u POST变量

Php PDO INSERT不使用$\u POST变量,php,sql,pdo,Php,Sql,Pdo,我对这件事非常恼火,希望这是一个容易的疏忽 我计划使用jqueryajax函数向这个PHP文件发送一组变量。我编写本节是为了将所有$u POST变量分配给php变量: foreach($_POST as $key => $value){ $$key = $value; } 它似乎起作用了,因为我可以像这样操纵变量: echo 'name: ' . $name . '<br>'; echo 'main_pic: ' . $main_pic . '<br>';

我对这件事非常恼火,希望这是一个容易的疏忽

我计划使用jqueryajax函数向这个PHP文件发送一组变量。我编写本节是为了将所有$u 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;
这不会运行-我不确定记录错误的最佳方法,以了解原因。如果我手动分配变量并注释掉我之前的$_PostShenhanigans,那么一切似乎都正常,插入运行良好

有什么线索吗?我认为这可能是因为数据库需要某种变量类型,但我认为我已经充分探讨了这一点

有人知道手动分配变量会起作用,但从$\u POST获取变量却不会起作用的原因吗

编辑:按照这些建议,我得到了一条错误消息 SQLSTATE[23000]:完整性约束冲突:键1的1062重复项“0”


好的,当我尝试这个插入时,我没有分配唯一的主键-我假设PDO会处理这个问题。处理分配唯一主键的最佳方法是什么?我希望避免让用户手动分配它

清空数据库表,看看它是否有效。。。很可能您的db表中有一个您试图覆盖的主键


还可以使用
解释清单

检查数据库表,如果需要,可以使用自动递增的主键。假设您使用mysql:

这不是答案,但看起来比评论好。您为什么要执行以下操作:

foreach($_POST as $key => $value){
    $$key = $value;
}
这是重新注册全局变量(有点)。使用上述代码,您可以很容易地覆盖局部变量,产生意外的结果,甚至引入安全漏洞

如果我发布
$\u post['is_admin']=1
或类似的东西会怎么样?不管怎样,我想你明白了。你刚才所做的是坏事,可能很危险

OP说: 好的,所以我在尝试时没有分配唯一的主键 这个插页——我是在假设PDO会处理这个问题的情况下写的。 处理分配唯一主键的最佳方法是什么?我想要 希望避免用户手动分配它

只需解决这一部分或您的问题-您只需使用一个不带引号的0

insert into table (id, name) values (0, 'Bob');
但正如您所说,如果它是一个自动正确递增的id,则不必这样做


在Mysql(<5)的旧版本中,你可以使用一个空字符串,当5.0出现时,这个字符串就爆炸了,以防任何人读到这篇文章时与之前未记录的功能相冲突。

像@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();
显然,这需要更多的验证、empty()检查等,但您已经明白了。此外,您可以通过回调查找添加更多验证/清理:

$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();

启用
PDO::ERRMODE\u WARNING
以查看它是否发现您有任何不当行为。如果您要将使用AJAX查询的URL放入浏览器,它应该(如果您已设置为显示所有错误)向您显示错误。或者,您的web文件夹根目录中可能有一个错误日志文件。这些信息中的任何信息都会有所帮助。启用错误代码并使用更多信息编辑问题。谢谢你的
prepare
/
execute
功能是否与“POST shenmanigs”相同?您的表结构是什么(
描述库存
)?接受了答案,但下面有一个很好的小讨论,讨论了为什么我在上面所做的是编码恐惧。谢谢这是通过给变量命名来解决的,还是应该完全避免这样做?我希望能够向表单中添加新字段,并最大限度地减少任何代码更改。@ThomasPatrickHorton您最好创建一个白名单键数组,并遍历它进行绑定。这将有助于最小化代码更改,并避免等待发生的注册全局灾难。@ThomasPatrickHorton如果您添加字段,您将不得不以任何方式更改代码,因为否则您的查询将无法工作。是的-这正是他们说不要滚动您自己的代码的原因。这实际上只是一个探索性项目——我知道有很多漏洞需要解决。谢谢你的提示!事实证明,这正是它是什么-现在我只是要修复它。谢谢非常有帮助——这是一个很好的开始。@ThomasPatrickHorton毫无疑问,鲍勃;我更新了一个更完整的版本。
// 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();