-1

正如标题所说,我在尝试将预制包装类用于PDO 准备语句时遇到问题。我无法在一行中一次插入超过 5 个值,这是我在编程期间第一次遇到此错误。这是类源代码,第一次尝试实现;

class db extends PDO {
private $error;
private $sql;
private $bind;
private $errorCallbackFunction;
private $errorMsgFormat;

public function __construct($dsn, $user="", $passwd="") {
    $options = array(
        PDO::ATTR_PERSISTENT => true, 
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    );
    try {
        parent::__construct($dsn, $user, $passwd, $options);
    } catch (PDOException $e) {
        $this->error = $e->getMessage();
    }
}

private function debug() {
    if(!empty($this->errorCallbackFunction)) {
        $error = array("Error" => $this->error);
        if(!empty($this->sql))
            $error["SQL Statement"] = $this->sql;
        if(!empty($this->bind))
            $error["Bind Parameters"] = trim(print_r($this->bind, true));

        $backtrace = debug_backtrace();
        if(!empty($backtrace)) {
            foreach($backtrace as $info) {
                if($info["file"] != __FILE__)
                    $error["Backtrace"] = $info["file"] . " at line " . $info["line"];  
            }       
        }

        $msg = "";
        if($this->errorMsgFormat == "html") {
            if(!empty($error["Bind Parameters"]))
                $error["Bind Parameters"] = "<pre>" . $error["Bind Parameters"] . "</pre>";
            $css = trim(file_get_contents(dirname(__FILE__) . "/error.css"));
            $msg .= '<style type="text/css">' . "\n" . $css . "\n</style>";
            $msg .= "\n" . '<div class="db-error">' . "\n\t<h3>SQL Error</h3>";
            foreach($error as $key => $val)
                $msg .= "\n\t<label>" . $key . ":</label>" . $val;
            $msg .= "\n\t</div>\n</div>";
        }
        elseif($this->errorMsgFormat == "text") {
            $msg .= "SQL Error\n" . str_repeat("-", 50);
            foreach($error as $key => $val)
                $msg .= "\n\n$key:\n$val";
        }

        $func = $this->errorCallbackFunction;
        $func($msg);
    }
}

public function delete($table, $where, $bind="") {
    $sql = "DELETE FROM " . $table . " WHERE " . $where . ";";
    $this->run($sql, $bind);
}

private function filter($table, $info) {
    $driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME);
    if($driver == 'sqlite') {
        $sql = "PRAGMA table_info('" . $table . "');";
        $key = "name";
    }
    elseif($driver == 'mysql') {
        $sql = "DESCRIBE " . $table . ";";
        $key = "Field";
    }
    else {  
        $sql = "SELECT column_name FROM information_schema.columns WHERE table_name = '" . $table . "';";
        $key = "column_name";
    }   

    if(false !== ($list = $this->run($sql))) {
        $fields = array();
        foreach($list as $record)
            $fields[] = $record[$key];
        return array_values(array_intersect($fields, array_keys($info)));
    }
    return array();
}

private function cleanup($bind) {
    if(!is_array($bind)) {
        if(!empty($bind))
            $bind = array($bind);
        else
            $bind = array();
    }
    return $bind;
}

public function insert($table, $info) {
    $fields = $this->filter($table, $info);
    $sql = "INSERT INTO " . $table . " (" . implode($fields, ", ") . ") VALUES (:" . implode($fields, ", :") . ");";
    $bind = array();
    foreach($fields as $field)
        $bind[":$field"] = $info[$field];
    return $this->run($sql, $bind);
}

public function run($sql, $bind="") {
    $this->sql = trim($sql);
    $this->bind = $this->cleanup($bind);
    $this->error = "";

    try {
        $pdostmt = $this->prepare($this->sql);
        if($pdostmt->execute($this->bind) !== false) {
            if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql))
                return $pdostmt->fetchAll(PDO::FETCH_ASSOC);
            elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql))
                return $pdostmt->rowCount();
        }   
    } catch (PDOException $e) {
        $this->error = $e->getMessage();    
        $this->debug();
        return false;
    }
}

public function select($table, $where="", $bind="", $fields="*") {
    $sql = "SELECT " . $fields . " FROM " . $table;
    if(!empty($where))
        $sql .= " WHERE " . $where;
    $sql .= ";";
    return $this->run($sql, $bind);
}

public function setErrorCallbackFunction($errorCallbackFunction, $errorMsgFormat="html") {
    //Variable functions for won't work with language constructs such as echo and print, so these are replaced with print_r.
    if(in_array(strtolower($errorCallbackFunction), array("echo", "print")))
        $errorCallbackFunction = "print_r";

    if(function_exists($errorCallbackFunction)) {
        $this->errorCallbackFunction = $errorCallbackFunction;  
        if(!in_array(strtolower($errorMsgFormat), array("html", "text")))
            $errorMsgFormat = "html";
        $this->errorMsgFormat = $errorMsgFormat;    
    }   
}

public function update($table, $info, $where, $bind="") {
    $fields = $this->filter($table, $info);
    $fieldSize = sizeof($fields);

    $sql = "UPDATE " . $table . " SET ";
    for($f = 0; $f < $fieldSize; ++$f) {
        if($f > 0)
            $sql .= ", ";
        $sql .= $fields[$f] . " = :update_" . $fields[$f]; 
    }
    $sql .= " WHERE " . $where . ";";

    $bind = $this->cleanup($bind);
    foreach($fields as $field)
        $bind[":update_$field"] = $info[$field];

    return $this->run($sql, $bind);
}
}   
        $db = new db("mysql:host=xxxx;dbname=xxxx", 'xxxxx', "xxxxx");


        $insert = array(
                    "network" => "High",
                    "to" => "High",
                    "from" => "High",
                    "headerType" => "High",
                    "date" => "High",
                    "priority" => "High",
                    "content" => "High"                     
                        );


        $db->insert("email_queue", $insert);

任何帮助都会被占用!

4

1 回答 1

0

我已经测试了这个包装器,它适用于 6 字段插入。证明:

<?php
ini_set('display_errors', true);
require_once __DIR__.'/class.db.php';
$db = new db('mysql:host=127.0.0.1;dbname=test', 'root', '');

$db->setErrorCallbackFunction('echo', 'text');

$createTableQuery = <<<SQL
CREATE TABLE IF NOT EXISTS `q17224744` (
  `name` varchar(100) NOT NULL,
  `lastname` varchar(100) NOT NULL DEFAULT '',
  `gender` char(1) NOT NULL DEFAULT '',
  `birthday` date NOT NULL,
  `city` varchar(100) NOT NULL DEFAULT '',
  `country` char(2) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SQL;
$db->run($createTableQuery);

$db->insert('q17224744', array(
  'name' => 'John',
  'lastname' => 'Doe',
  'gender' => 'm',
  'birthday' => '1971-12-03',
  'city' => 'London',
  'country' => 'GB',
));

我认为您的问题与插入中的错误值有关。如果你没有设置错误回调函数,包装器库不会告诉你错误。尝试使用setErrorCallbackFunction上面示例中的功能启用调试输出。

PS 这个包装器有违反直觉的行为——默认情况下,当异常来临时它什么也不说。仅当程序员设置异常处理程序时,默认抛出异常和静默会好得多。

于 2013-06-20T23:41:21.103 回答