【问题标题】:How do you perform a dynamic php, PDO prepared statement Update?你如何执行动态的php、PDO准备语句更新?
【发布时间】:2012-01-12 05:50:45
【问题描述】:

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

警告:PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]:参数号无效:参数未定义 在 /Users/scottmcpherson/Sites/phpsites/projectx/application/models/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() 方法现在看起来像: 公共函数更新(){

    $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) 我得到: 数组(2) { [":username"]=> string(5) "Jonny" [":password"]=> string(9) "Appleseed" } 仍然出现同样的错误。

【问题讨论】:

  • 请发$this-&gt;properties()的内容
  • 已发布。它就在连接方法的正下方。 properties 方法只是创建一个关联数组,其中包含在类中定义的属性。所以在这种情况下,数组看起来像: Array ( [username] => Jonny [password] => Appleseed )
  • 我的意思是通过var_dump($this-&gt;properties() 发布实际的变量内容。如果数组键不以冒号开头,则语句执行将失败。它们应该看起来像 Array ( [:username] =&gt; Jonny [:password] =&gt; Appleseed )
  • 我明白你在说什么。我不需要用我的插入方法()来做这件事。如果我 var 转储属性,我会得到:array(2) { ["username"]=> string(5) "Jonny" ["password"]=> string(9) "Appleseed" }.
  • @Michael 我创建了一个在每个键的开头添加 : 的方法。 var_dump 显示:'array(2) { [":username"]=> string(5) "Jonny" [":password"]=> string(9) "Appleseed" }'。我,$this->properties,使用我的新方法 '$this->colProperties()。仍然出现错误。我想我会坚持下去。

标签: php mysql pdo


【解决方案1】:

我不认为将参数传递给 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()execute() 之前显示$this-&gt;properties()

var_dump($this->properties())

确保您的键完全匹配。

【讨论】:

  • @Scott,您可以编辑您的问题并在那里提供更多信息。 cmets 中的代码不可读。无论如何,我没有发现明显的错误。
【解决方案2】:

错误是介于两者之间

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

WHERE 子句之间需要有一个空格,因为 PolishVals() 方法不会在 implode 之后添加空格。所以,你会有类似的东西

UPDATE User SET city=:city, location=:locationWHERE User.id=28

导致错误的原因。 简单的错误。

【讨论】:

    猜你喜欢
    • 2020-04-14
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 2010-11-30
    • 2012-02-16
    相关资源
    最近更新 更多