为什么这个准备好的插入 MySql 与 PDO 插入错误的值?

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

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

我以 table 中的每一行结束,其中 map_point_x = 7 且 map_point_y = 3。map_terrain 字段具有正确的值。

这是怎么跑偏了?

$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、...)at查询执行时刻。这将是循环后的最终值,即您示例中的 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();