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

Posted

技术标签:

【中文标题】如何在 php 中使用 bind_result() 而不是 get_result()【英文标题】:How to use bind_result() instead of get_result() in php 【发布时间】:2014-05-14 10:25:56 【问题描述】:

我正在为 uni 开发一个项目,并且一直在基于 user_id 的表中的 testing serverget all devices 上使用以下代码:

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

任何帮助将不胜感激

【问题讨论】:

你可以在这里得到一些参考:php.net/manual/pt_BR/mysqli-stmt.bind-result.php 这可能意味着您的生产机器正在使用 PHP us2.php.net/manual/en/mysqli-stmt.get-result.php 它实际上使用的是 PHP 5.4.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

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案3】:

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

尽管如此,您仍然可以使用 mysqli 进行 'select *' 查询,并使用字段名称获取结果 - 尽管它比使用 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>";

【讨论】:

【参考方案4】:

到现在为止,您肯定已经掌握了绑定到多个变量的想法。但是,不要相信关于不使用“SELECT *”和 bind_result() 的警告。您可以保留您的“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-&gt;fetch()) 之前调用这一事实可以看出。

但是有一个问题:因为该语句已绑定到 $bound_assoc 中的引用,所以它们将随着每个$stmt-&gt;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;

【讨论】:

【参考方案5】:

假设您不能使用 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;

这会创建一个临时数组并将每一行的数据存储在其中,然后将其推送到主数组。据我所知,您不能在bind_result() 中使用SELECT *。相反,您将不得不在SELECT 之后输入您想要的所有字段

【讨论】:

以上是关于如何在 php 中使用 bind_result() 而不是 get_result()的主要内容,如果未能解决你的问题,请参考以下文章

PHP PHP准备语句 - 带有未定义的变量数传递给bind_result()

mysqli_stmt::bind_result():绑定变量的数量与准备好的语句中的字段数量不匹配

未使用 mysqli bind_result 从数据库中获取值

不确定分配时 PHP 数组在做啥

MySQL性能优化方案

如何将js的变量在php中使用