Переменное количество столбцов, возвращаемых в подготовленном операторе mysqli - PullRequest
1 голос
/ 27 мая 2010

У меня есть ситуация, когда генерируется динамический запрос, который может выбрать от 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 ]

3 голосов
/ 12 марта 2013

Я предпочитаю , а не , чтобы использовать 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 голос
/ 28 мая 2010

Используя предложение 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          
    }
0 голосов
/ 12 марта 2013

Именно по этой причине mysqli никогда не следует использовать с подготовленными операторами.
Таким образом, вместо этого вы должны использовать PDO , что сделает executePreparedStatement () в three линии:

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']);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...