为什么这个准备好的插入到MySql中的PDO插入了错误的值


Why is this prepared insert into MySql with PDO inserting wrong value?

我正在尝试为数据库表播种映射点,映射点反映jpg映射中的每个点。该代码是对3x7小图像的测试,但该应用程序适用于更大的地图,其中地图点信息将与每个点关联并存储在表中。map_terain字段表示给定坐标的颜色十六进制值。但正是相关的x,y值出了问题。

我最终得到了表中map_point_x=7和map_point_y=3的每一行。map_trrain字段的值正确。

这是怎么误入歧途的?

$image_filespec = '../test.jpg';
$map_id = 1;
include_once '../includes/functions.php';
function heximagecolorat($image, $x, $y, $sharp_prefix = TRUE) {
        $rgb = imagecolorat($image, $x, $y);
        $r = ($rgb >> 16) & 0xFF;
        $g = ($rgb >> 8) & 0xFF;
        $b = $rgb & 0xFF;
   If ($sharp_prefix == TRUE) {
       $hex = "#";
   } else {
       $hex = "";
   }
   $hex .= str_pad(dechex($r), 2, "0", STR_PAD_LEFT);
   $hex .= str_pad(dechex($g), 2, "0", STR_PAD_LEFT);
   $hex .= str_pad(dechex($b), 2, "0", STR_PAD_LEFT);
   return $hex; // returns the hex value including the number sign (#)
}

if ($image_filespec == 'nnn.jpg' ){
    echo 'you need to edit teh php file to make this work and alter $image_filespec as appropriate';
    return;
}

//$result = query_db('SELECT * FROM users');
//  
//while($row = $result->fetch()){
//    echo $row['uID'] . " - " . $row['uUsername'] . "<br/>";
//}
$image = imagecreatefromjpeg($image_filespec); // imagecreatefromjpeg/png/
$width = imagesx($image);
$height = imagesy($image);
$colors = array();

for ($y = 0; $y < $height; $y++) {
    for ($x = 0; $x < $width; $x++) {
        $colors[] = heximagecolorat($image, $x, $y, $sharp_prefix=FALSE) ; 
    } 
}
// connect and insert arrya to database $row in this context is talking about table row as opposed to row from the original image
$dbh = db_connect();
$query = "INSERT INTO map_points (  map_id, map_point_x, map_point_y, map_terrain ) VALUES "; //Prequery
$qPart = array_fill(0, count($colors), "( ?, ?, ?, ?)");
$query .=  implode(",",$qPart);
$stmt = $dbh -> prepare($query); 
$i = 1;
$point=0;
for ($y = 0; $y < $height; $y++) {
    for ($x = 0; $x < $width; $x++) { //bind the values one by one
        $stmt -> bindParam($i++, $map_id);
        $stmt -> bindParam($i++, $x);
        $stmt -> bindParam($i++, $y);
        $stmt -> bindParam($i++, $colors[$point]);
        $point += 1;
    }
}
$temp=$stmt;
$stmt -> execute(); //execute

我认为问题在于PDOStatement::bindParam()的使用:它在查询执行时绑定变量(如$x$y…)的值。这将是循环之后的最终值,即您的示例中的37

请改用PDOStatement::bindValue()

此外,如果为每个点执行语句,而不是使用行数尽可能多的元组,则可能更容易阅读和维护代码。换句话说,使用多个INSERT INTO map_points(map_id, map_point_x, map_point_y, map_terrain) VALUES (?, ?, ?, ?)而不是一个INSERT INTO map_points(map_id, map_point_x, map_point_y, map_terrain) VALUES (?, ?, ?, ?), (?, ?, ?, ?), ...。多元组具有更好的性能,但通过将INSERT语句封装在事务中可以达到类似的性能。

$dbh = db_connect();
$stmt = $dbh->prepare('INSERT INTO map_points (map_id, map_point_x, map_point_y, map_terrain) VALUES (?, ?, ?, ?)');
$y = 0;
$x = 0;
$stmt->bindValue(1, $map_id);
$stmt->bindParam(2, $x);
$stmt->bindParam(3, $y);
$dbh->beginTransaction();
for (; $y < $height; $y++) {
    for (; $x < $width; $x++) {
        $stmt->bindValue(4, heximagecolorat($image, $x, $y, $sharp_prefix=FALSE));
        $stmt->execute();
    }
}
$dbh->commit();