动态准备插入语句

时间:2015-05-20 19:36:07

标签: php mysqli prepared-statement

让我先说一下,我刚刚开始学习准备好的陈述,这可能只是为了掌握,但我想尝试。

我正在尝试在DatabaseObject类中创建一个动态创建函数。该函数将采用任意数量的不同允许数据类型的任意数量的值。不幸的是,我尝试过的一切都没有效这是代码。

public function create() {
    $db = Database::getInstance();
    $mysqli = $db->getConnection();
    //array of escaped values of all types in the object
    $attributes = $this->sanitized_attributes();

    $check = $mysqli->stmt_init();

    $paramType = array();

    $types = ''; $bindParam = array(); $where = ''; $count = 0;

    foreach($attributes as $key=>$val)
    {
        $types .= 'i';
        $bindParam[] = '$p'.$count.'=$param["'.$key.'"]'; 
        $where .= "$key = ? AND ";
        $count++;
    }

    $sql_query = "INSERT INTO `".static::$table_name."` ";  

    $sql_query .= "VALUES (";

    foreach ($attributes as $key => $value) {
        $valueType = gettype($value);

        if ($valueType == 'string') {
            $sql_query .= "?,";
            array_push($paramType, "s");
        } else if ($valueType == 'integer') {
            $sql_query .= "?,";
            array_push($paramType, "i");
        } else if ($valueType == 'double') {
            $sql_query .= "?,";
            array_push($paramType, "d");
        } else {
            $sql_query .= "?,";
            array_push($paramType, "b");
        }           
    }

    $sql_query .= ")";
}

此时我完全迷失了我的想法。

我已经准备好了简单的预处理语句,但是这个语句更加复杂和动态,我不知道我是否正确地处理了这个过程以及在sql_query之后要做什么才能获得这个工作。这里的所有问题都让我感到困惑,所以如果我得到了当前代码的指导,看看我哪里出错了会有所帮助。

感谢您的时间。

2 个答案:

答案 0 :(得分:0)

public function create() {
    $db = Database::getInstance();
    $mysqli = $db->getConnection();

    $attributes = $this->sanitized_attributes();

    $tableName = static::$table_name;

    $columnNames = array();
    $placeHolders = array();
    $values = array();

    foreach($attributes as $key=>$val)
    {
        // skip identity field
        if ($key == static::$identity)
            continue;
        $columnNames[] = '`' . $key. '`';
        $placeHolders[] = '?';
        $values[] = $val;
    }

    $sql = "Insert into `{$tableName}` (" . join(',', $columnNames) . ") VALUES (" . join(',', $placeHolders) . ")";

    $statement = $mysqli->stmt_init();
    if (!$statement->prepare($sql)) {
        die("Error message: " . $mysqli->error);
        return;
    }

    $bindString = array();
    $bindValues = array();

    // build bind mapping (ssdib) as an array
    foreach($values as $value) {
        $valueType = gettype($value);

        if ($valueType == 'string') {
            $bindString[] = 's';
        } else if ($valueType == 'integer') {
            $bindString[] = 'i';
        } else if ($valueType == 'double') {
            $bindString[] = 'd';
        } else {
            $bindString[] = 'b';
        }

        $bindValues[] = $value;
    }

    // prepend the bind mapping (ssdib) to the beginning of the array
    array_unshift($bindValues, join('', $bindString));

    // convert the array to an array of references
    $bindReferences = array();
    foreach($bindValues as $k => $v) {
        $bindReferences[$k] = &$bindValues[$k];
    }

    // call the bind_param function passing the array of referenced values
    call_user_func_array(array($statement, "bind_param"), $bindReferences);

    $statement->execute();  
    $statement->close();

    return true;
}

我想特别注意我自己没有找到解决方案。我有很长一段时间开发人员找到这个解决方案,并希望将它发布给那些可能想知道的人。

答案 1 :(得分:0)

在我试图为完全相同的问题找到解决方案时,我不小心发现了您的旧帖子。我的代码似乎更具优势,因为其中仅包含一个循环。因此,我将其添加为这篇文章的可能改进:

    $sqlquery = $this->MySQLiObj->prepare($dummy);

    $paramQuery = array();
    $paramQuery[0] = '';

    $n = count($valueArray);
    for($i = 0; $i < $n; $i++) {
        $checkedDataType = $this->returnDataType($valueArray[$i]);
        if($checkedkDataType==false) {
            return false;
        }
        $paramQuery[0] .= $checkedDataType;
        /* with call_user_func_array, array params must be passed by reference -> & */
    $paramQuery[] = &$valueArray[$i];
    }

    /*In array(): sqlquery(object)->bind_param(method)*/
    call_user_func_array(array($sqlquery, 'bind_param'), $paramQuery);
    $sqlquery->execute();
    /*Can be used identical to $result = $mysqli->query()*/
    $result = $this->MySQLiObj->get_result();
    $sqlquery->close();

将函数returnDataType()与switch语句一起使用,如果偏爱某种数据类型,则此方法可能会更快。

    private function returnDataType($input) {
    switch(gettype($input)) {
        case string: return 's';
        case double: return 'd';
        case integer: return 'i';
        default: $this->LOG->doLog("Unknown datatype during database access."); return 's';
    }
}