mysqli预处理语句中返回的可变数量的列

时间:2010-05-27 19:39:22

标签: php mysqli prepared-statement

我的情况是生成一个动态查询,可以在多个表中选择1到300多个不同的列。它目前只能正常进行查询,但是我在使用预准备语句时遇到的问题是我不知道如何处理这样一个事实,即我不知道每次要求多少列和因此不知道如何处理结果。 我认为绑定语句有用的原因是因为一旦这个查询运行一次,它将 很可能 (尽管不总是)使用完全相同的参数再次运行。

目前我有这样的事情:

$rows = array();
$this->statement = $this->db->prepare($query);
$this->statement->bind_param('i',$id);
$this->statement->execute();
$this->statement->bind_result($result);
while($this->statement->fetch())
{
   $rows[] = $result;
}

我知道这不能按照我的意愿运行,我的问题是如何从查询中恢复数据。是否可以按列名称将列重新放回关联数组中,就像标准的mysqli查询一样?

3 个答案:

答案 0 :(得分:3)

我希望使用eval,这是我的解决方案(类似于ashurexm):

$md = $stmt -> result_metadata();
$fields = $md -> fetch_fields();
$result = new stdClass(); // Actual result object
$params = array(); // Array of fields passed to the bind_result method
foreach($fields as $field) {
    $result -> {$field -> name} = null;
    $params[] = &$result -> {$field -> name};
}
call_user_func_array(array($stmt, 'bind_result'), $params);

答案 1 :(得分:1)

使用VolkerK的mysqli_statement->result_metadata()建议我能够将以下代码组合在一起,完成我正在寻找的东西,尽管性能并不比使用标准查询快。我得到statement->result_metadata()来构建一个关联数组来调用bind_result。我将bind_result语句构建为字符串并eval。我知道这不是特别安全,但这是我的第一次通过。

public function executePreparedStatement()
{
    if($this->statement->execute())
    {
        $this->record = array();
        $md = $this->statement->result_metadata();
        $fields = $md->fetch_fields();

        $bindResult = '$this->statement->bind_result(';
        foreach($fields as $field)
        {
            $bindResult .= "\$this->record['" . $field->name . "'],";
        }

        $bindResult = substr($bindResult,0,strlen($bindResult) - 1) . ');';

        eval($bindResult);
        return true;
    }
    else
    {
        $this->error = $this->db->error;
        return false;
    }
}

    ...
    $this->prepareStatement($query);
    $this->bindParameter('i',$runId);
    if($this->executePreparedStatement())
    {
        $report = new Report();
        while($this->statement->fetch())
        {
            $row = $this->record;
            $line = array();
            foreach($row as $key => &$value)
            {
                array_push($line,$value);
            }
            $report->addLine($line);
        }
        return $report          
    }

答案 2 :(得分:0)

这就是为什么mysqli永远不应该用于准备好的陈述的原因 因此,您必须使用PDO,这将使您的executePreparedStatement()成为三个行:

function executePreparedStatement($sql,$params) {
    $stm = $this->db->prepare($sql);
    $stm->execute($params);
    return $stm->fetchAll();
}

像这样使用

$sql  = "SELECT * from news WHERE category=?";
$data = $this->executePreparedStatement($sql,$_GET['category']);