动态绑定mysqli_stmt参数然后绑定结果(PHP)

Nik*_*las 6 php dynamic prepared-statement sqlbindparameter

我正在尝试动态绑定mysql_stmt参数并在关联数组中获取结果.我在stackoverflow上找到了这篇文章,其中Amber发布了以下代码的答案:

原帖: 如何用准备好的语句制作一个合适的mysqli扩展类?

"假设你实际上想要编写自己的版本(而不是利用其他答案所建议的现有库之一 - 那些也是很好的选择)......

以下是一些您可能会发现有用的功能.第一个允许您将查询的结果绑定到关联数组,第二个允许您传入两个数组,一个是有序的键数组,另一个是这些键的数据的关联数组,并将数据绑定到准备好的声明:"

function stmt_bind_assoc (&$stmt, &$out) {
    $data = mysqli_stmt_result_metadata($stmt);
    $fields = array();
    $out = array();

$fields[0] = $stmt;
$count = 1;

while($field = mysqli_fetch_field($data)) {
    $fields[$count] = &$out[$field->name];
    $count++;
}
call_user_func_array(mysqli_stmt_bind_result, $fields);

}

function stmt_bind_params($stmt, $fields, $data) {
    // Dynamically build up the arguments for bind_param
    $paramstr = '';
    $params = array();
    foreach($fields as $key)
    {
        if(is_float($data[$key]))
            $paramstr .= 'd';
        elseif(is_int($data[$key]))
            $paramstr .= 'i';
        else
            $paramstr .= 's';
        $params[] = $data[$key];
    }
    array_unshift($params, $stmt, $paramstr);
    // and then call bind_param with the proper arguments
    call_user_func_array('mysqli_stmt_bind_param', $params);
}
Run Code Online (Sandbox Code Playgroud)

我尝试研究代码以了解它的作用,并且我已经使第二个函数正常工作但我不知道我应该做些什么才能使用第一个函数.我如何使用它来检索类似于mysqli_result :: fetch_assoc()的数组?

我希望能够像以前那样使用结果:

while ($row = mysql_fetch_array($result)){
  echo $row['foo']." ".$row['bar'];
}
Run Code Online (Sandbox Code Playgroud)

请帮助我在这方面取得一些进展:)

Emm*_*uel 13

好的,这是一种方法:

编辑,修复获取多行时的错误

$sql = "SELECT `first_name`,`last_name` FROM `users` WHERE `country` =? AND `state`=?";
$params = array('Australia','Victoria');

/*
    In my real app the below code is wrapped up in a class 
    But this is just for example's sake.
    You could easily throw it in a function or class
*/

// This will loop through params, and generate types. e.g. 'ss'
$types = '';                        
foreach($params as $param) {        
    if(is_int($param)) {
        $types .= 'i';              //integer
    } elseif (is_float($param)) {
        $types .= 'd';              //double
    } elseif (is_string($param)) {
        $types .= 's';              //string
    } else {
        $types .= 'b';              //blob and unknown
    }
}
array_unshift($params, $types);

// Start stmt
$query = $this->connection->stmt_init(); // $this->connection is the mysqli connection instance
if($query->prepare($sql)) {

    // Bind Params
    call_user_func_array(array($query,'bind_param'),$params);

    $query->execute(); 

    // Get metadata for field names
    $meta = $query->result_metadata();

    // initialise some empty arrays
    $fields = $results = array();

    // This is the tricky bit dynamically creating an array of variables to use
    // to bind the results
    while ($field = $meta->fetch_field()) { 
        $var = $field->name; 
        $$var = null; 
        $fields[$var] = &$$var; 
    }


    $fieldCount = count($fieldNames);

// Bind Results                                     
call_user_func_array(array($query,'bind_result'),$fields);

$i=0;
while ($query->fetch()){
    for($l=0;$l<$fieldCount;$l++) $results[$i][$fieldNames[$l]] = $fields[$fieldNames[$l]];
    $i++;
}

    $query->close();

    // And now we have a beautiful
    // array of results, just like
    //fetch_assoc
    echo "<pre>";
    print_r($results);
    echo "</pre>";
}
Run Code Online (Sandbox Code Playgroud)


mat*_*ino 9

如果只选择了一行,Emmanuel的答案就可以正常工作!如果查询选择多行,则$ results-Array为每一行保存结果,但结果始终用最后一个条目填充.fetch()稍有变化 - 虽然效果很好.

$ sqlStmt是一个字符串,填充了mysql查询

$ params是一个数组,填充了应该传递的变量

$ results是一个空数组,用于保存结果

    if (!is_string($sqlStmt) || empty($sqlStmt)) {
        return false;
    }

    // initialise some empty arrays
    $fields = array();
    $results = array();

    if ($stmt = $this->prepare($sqlStmt)) {
        // bind params if they are set
        if (!empty($params)) {
            $types = '';
            foreach($params as $param) {
                // set param type
                if (is_string($param)) {
                    $types .= 's';  // strings
                } else if (is_int($param)) {
                    $types .= 'i';  // integer
                } else if (is_float($param)) {
                    $types .= 'd';  // double
                } else {
                    $types .= 'b';  // default: blob and unknown types
                }
            }

            $bind_names[] = $types;
            for ($i=0; $i<count($params);$i++) {
                $bind_name = 'bind' . $i;       
                $$bind_name = $params[$i];      
                $bind_names[] = &$$bind_name;   
            }

            call_user_func_array(array($stmt,'bind_param'),$bind_names);
        }

        // execute query
        $stmt->execute();

        // Get metadata for field names
        $meta = $stmt->result_metadata();

        // This is the tricky bit dynamically creating an array of variables to use
        // to bind the results
        while ($field = $meta->fetch_field()) { 
            $var = $field->name; 
            $$var = null; 
            $fields[$var] = &$$var;
        }

        // Bind Results
        call_user_func_array(array($stmt,'bind_result'),$fields);

        // Fetch Results
        $i = 0;
        while ($stmt->fetch()) {
            $results[$i] = array();
            foreach($fields as $k => $v)
                $results[$i][$k] = $v;
            $i++;
        }

        // close statement
        $stmt->close();
    }
Run Code Online (Sandbox Code Playgroud)