如何执行一个动态的php、PDO准备语句更新


How do you perform a dynamic php, PDO prepared statement Update?

我很难找到关于pdo update prepared语句的好的文档,甚至更难以找到关于使用pdo prepared语句动态更新数据库的文档。我已经得到了我的动态插入工作,但我有问题与更新。我得到的错误是:

: PDOStatement::execute() [PDOStatement .execute]:SQLSTATE[HY093]: Invalid parameter number:参数没有定义在/用户/scottmcpherson/网站/phpsites projectx/应用程序/模型/db.php第91行错误

下面是我创建的类,减去两个与这个问题无关的方法:

<?php 
require_once("../config/main.php");
class Database{
protected static $dbFields = array('username', 'password');
public $db;
public $tableName = 'users';
public $id = 1;
public $username = "Jonny";
public $password = "Appleseed";
public function __construct() {
    $this->connect();
}
public function connect(){
try {
    $this->db = new PDO("mysql:host=".DB_SERVER."; dbname=".DB_NAME, DB_USER, DB_PASS);
    } catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    }
}
public function properties() {
    $properties = array();
    foreach (self::$dbFields as $field) {
        if (isset($this->field) || property_exists($this, $field)) {
            $properties[$field] = $this->$field;            
        }
    }
    return $properties;
}
public function propertyValues() {  
    $property = $this->properties();
    $propertyValues = array();
    foreach ($property as $key => $value) {
        $propertyValues = ":" . implode(", :", array_keys($property));
    }
    return $propertyValues;
}
public function polishedVals(){
       // The end result of this function is:
       // username=:username, password=:password
    $props = $this->properties();
    $phaseOne = array();
    foreach ($props as $key => $value) {
        $phaseOne[$key] = ":".$key;
    }
        $phaseTwo = array();
        foreach ($phaseOne as $key => $value) {
            $phaseTwo[] = "{$key}={$value}";
        }
        $polishedVals = implode(", ", $phaseTwo);
    return $polishedVals;
}
public function update(){
    $stmt  = "UPDATE ". $this->tableName." SET ";
    $stmt .= $this->polishedVals();
    $stmt .= "WHERE id=" . $this->id;   
    $stmt  = $this->db->prepare($stmt);
    if($stmt->execute($this->properties())) {
        echo "yes";
    } else {
        echo "error ";
    }
}
}
$database = new Database();
echo$database->update();

 ?>

将所有变量替换为实际值后,使用update()方法得到的结果如下所示:

public function update(){
    $stmt  = "UPDATE users SET ";
    $stmt .= "username=:username, password=:password ";
    $stmt .= "WHERE id=1";  
    $stmt  = $this->db->prepare($stmt);
    if($stmt->execute($this->properties())) {
        echo "yes";
    } else {
        echo "error ";
    }
}

除了发现这个问题,如果你看到这个代码的任何其他问题,请让我知道。我对PHP还是个新手。

编辑:我现在已经创建了一个新方法,在属性数组中的每个键的开头添加一个:
public function colProperties(){
    $properties = $this->properties();
    $withCols = array();
    foreach($properties as $key => $value){
        $withCols[":".$key] = $value;
    }
    return $withCols;
}

所以我的update()方法现在看起来像:公共函数update(){

    $stmt  = "UPDATE ". $this->tableName." SET ";
    $stmt .= $this->polishedVals();
    $stmt .= "WHERE id=" . $this->id;   
    $stmt  = $this->db->prepare($stmt);
    if($stmt->execute($this->colProperties())) {
        echo "yes";
    } else {
        echo "error ";
    }
}

,如果我var_dump($this->colProperties),我得到:Array (2) {[":username"]=> string(5)"Jonny" [":password"]=> string(9)"苹果子"}仍然得到相同的错误

我不认为将参数传递给UPDATE查询需要使用与SELECT查询不同的方法。PDOStatement->execute()手册页中的信息应该适用:

<?php
/* Execute a prepared statement by passing an array of insert values */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
?>

你正在使用命名参数,所以execute()需要一个关联数组。使用var_dump()将$this->properties()显示在execute()前面:

var_dump($this->properties())

错误在于

$stmt .= $this->polishedVals();
$stmt .= "WHERE id=" . $this->id; 

WHERE子句之间需要有一个空格,因为polishedVals()方法不会在内爆破之后添加空格。因此,你会得到像

这样的东西
UPDATE User SET city=:city, location=:locationWHERE User.id=28

导致错误。简单的错误。