如何在php中使用bind_result()而不是get_result()

时间:2014-04-02 21:18:21

标签: php mysql sql mysqli prepared-statement

我正在为uni开发一个项目,并且已经在基于testing server的表格的get all devicesuser_id上使用了以下代码:

public function getAllDevices($user_id) {
    $stmt = $this->conn->prepare("SELECT * FROM devices WHERE  primary_owner_id = ?");
    $stmt->bind_param("i", $user_id);
    $stmt->execute();
    $devices = $stmt->get_result();
    $stmt->close();
    return $devices;
}

这在我的测试服务器上工作正常,但在迁移到大学项目服务器时返回此错误:

Call to undefined method mysqli_stmt::get_result()

有些谷歌搜索建议使用bind_result()代替get_result(),但我不知道如何在表格中执行此操作all fields。大多数示例仅显示返回one field

非常感谢任何帮助

5 个答案:

答案 0 :(得分:7)

假设您无法使用get_result()并且想要一系列设备,您可以这样做:

public function getAllDevices($user_id) {
    $stmt = $this->conn->prepare("SELECT device_id, device_name, device_info FROM devices WHERE  primary_owner_id = ?");
    $stmt->bind_param("i", $user_id);
    $stmt->execute();
    $stmt->bind_result($id, $name, $info);
    $devices = array();

    while($stmt->fetch()) {
        $tmp = array();
        $tmp["id"] = $id;
        $tmp["name"] = $name;
        $tmp["info"] = $info;
        array_push($devices, $tmp);
    }
    $stmt->close();
    return $devices;
}

这将创建一个临时数组并存储其中每行的数据,然后将其推送到主数组。据我所知,您无法在SELECT *中使用bind_result()。相反,您会烦恼地在SELECT

之后输入所需的所有字段

答案 1 :(得分:3)

到目前为止,您已经掌握了绑定多个变量的想法。但是,不要相信不使用带有bind_result()的“SELECT *”的警告。您可以保留“SELECT *”语句...甚至在您的服务器上要求您使用bind_result(),但它有点复杂,因为您必须使用PHP的call_user_func_array()作为传递任意的方式(因为“SELECT” *“)bind_result()的参数数量。在我之前的其他人发布了一个方便的功能,在这些论坛的其他地方这样做。我把它包括在这里:

// Take a statement and bind its fields to an assoc array in PHP with the same fieldnames
function stmt_bind_assoc (&$stmt, &$bound_assoc) {
    $metadata = $stmt->result_metadata();
    $fields = array();
    $bound_assoc = array();

    $fields[] = $stmt;

    while($field = $metadata->fetch_field()) {
        $fields[] = &$bound_assoc[$field->name];
    }    
    call_user_func_array("mysqli_stmt_bind_result", $fields);
}

现在,为了使用它,我们做了类似的事情:

function fetch_my_data() {
    $stmt = $conn->prepare("SELECT * FROM my_data_table");
    $stmt->execute();
    $result = array();
    stmt_bind_assoc($stmt, $row);
    while ($stmt->fetch()) {
         $result[] = array_copy($row);
    }
    return $result;
}

现在,fetch_my_data()将返回一个关联数组数组...所有设置为编码为JSON或其他。

这有点狡猾,这里发生了什么。 stmt_bind_assoc()在传递给它的引用($ bound_assoc)上构造一个空的关联数组。它使用result_metadata()和fetch_field()来获取返回字段的列表,并且(在while循环中使用该单个语句)在$bound_assoc中使用该字段名创建一个元素,并在$ fields中附加对它的引用阵列。然后将$ fields数组传递给mysqli_stmt_bind_result。真正光滑的部分是没有实际值传递到$ bound_assoc,但。所有从查询中获取数据都发生在fetch_my_data()中,正如您在stmt_bind_assoc()之前调用while($stmt->fetch())的事实所示。

但是有一个问题:因为语句绑定到$ bound_assoc中的引用,所以它们将随每个$stmt->fetch()而改变。因此,您需要制作$ row的深层副本。如果不这样做,$ result数组中所有行将包含相同的内容:SELECT中返回的最后一行。所以,我正在使用我在Google上找到的一个小型array_copy()函数:

function array_copy( array $array ) {
    $result = array();
    foreach( $array as $key => $val ) {
        if( is_array( $val ) ) {
            $result[$key] = arrayCopy( $val );
        } elseif ( is_object( $val ) ) {
            $result[$key] = clone $val;
        } else {
            $result[$key] = $val;
        }
    }
    return $result;
}

答案 2 :(得分:1)

要使用bind_result(),您无法使用SELECT *的查询。

相反,您必须选择单个列名称,然后以相同的顺序绑定结果。这是一个例子:

$stmt = $mysqli->prepare("SELECT foo, bar, what, why FROM table_name WHERE id = ?");
$stmt->bind_param("i", $id);
if($stmt->execute()) {
    $stmt->bind_result($foo, $bar, $what, $why);
    if($stmt->fetch()) {
        $stmt->close();
    }else{
        //error binding result(no rows??)
    }
}else{
    //error with query
}

答案 3 :(得分:1)

您的问题表明您在本地服务器上安装了MySQL Native driver (MySQLnd),但学校项目服务器上缺少MySQLnd。因为get_result()需要MySQLnd。

因此,如果您仍想在学校项目服务器上使用get_result()而不是bind_result(),那么您应该在学校项目服务器上安装MySQLnd。

答案 4 :(得分:0)

get_result()现在只能通过安装MySQL本机驱动程序(mysqlnd)在PHP中使用。在某些环境中,可能无法或不希望安装mysqlnd。

尽管如此,您仍然可以使用mysqli来选择*'查询,并使用字段名称获取结果 - 虽然它比使用get_result()稍微复杂一些,并涉及使用php的call_user_func_array()函数。请参阅下面的示例,该示例执行简单的选择*'查询,并将结果(带列名称)输出到HTML表:

$maxaccountid=100;
$sql="select * from accounts where account_id<?";
$stmt = $mysqli->prepare($sql);      
$stmt->bind_param('i', $maxaccountid); 
$stmt->execute();
print "<table border=1>";
print "<thead><tr>";   
$i=0;
$meta = $stmt->result_metadata();
$query_data=array();  
while ($field = $meta->fetch_field()) { 
  print "<th>" . $field->name . "</th>";
  $var = $i;
  $$var = null; 
  $query_data[$var] = &$$var; 
  $i++;    
}
print "</tr></thead>";
$r=0;
call_user_func_array(array($stmt,'bind_result'), $query_data); 
while ($stmt->fetch()) {                   
  print "<tr>";
  for ($i=0; $i<count($query_data); $i++) { 
    print "<td>" .  $query_data[$i] . "</td>"; 
  }
  print "</tr>";
  $r++;        
}
print "</table>";
$stmt->close();
print $r . " Records<BR>";