Sütunların değişebilen miktarda mysqli hazırlanan açıklamada döndü

3 Cevap php

I have a situation where a dynamic query is being generated that could select anywhere from 1 to over 300 different columns across multiple tables. It currently works fine just doing a query, however the issue I'm running into in using a prepared statement is that I do not know how to handle the fact that I don't know how many columns I will be asking for each time and therefor don't know how to process the results. The reason I believe a bind statement will help is because once this query is run once, it will most likely (though not always) be run again with the exact same parameters.

Şu anda böyle bir şey var:

$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;
}

Ben bunu istiyorum bu işe yaramazsa biliyorum, benim soru nasıl sorgunun geri veri almak yapmaktır. Standart bir mysqli sorgu gibi, geri sütun adıyla bir ilişkisel dizi sütunları getirmek mümkün mü?

3 Cevap

Performans daha hızlı, standart bir sorgu kullanarak daha olmasa mysqli_statement->result_metadata() ben arıyorum ne yapar aşağıdaki kodu birlikte moda başardı ve VolkerK önerisini kullanma. Ben statement->result_metadata() üzerine bind_result aramak için ilişkilendirilebilir bir dizi oluşturmak için olsun. Ben bir dizge olarak bind_result açıklama kurmak ve eval o. Ben bu özellikle güvenli değil biliyorum ama bu benim ilk geçiş olduğunu.

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          
    }

I-not eval, bu (ashurexm benzer) benim çözüm kullanımı Prever:

$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);

This is the very reason why mysqli should never be used with prepared statements.
So, you have to use PDO instead, which will make your executePreparedStatement() into three lines:

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

Bu gibi kullanılabilir

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