Вызов неопределенного метода mysqli_stmt :: get_result

Вот мой код:

include 'conn.php'; $conn = new Connection(); $query = 'SELECT EmailVerified, Blocked FROM users WHERE Email = ? AND SLA = ? AND `Password` = ?'; $stmt = $conn->mysqli->prepare($query); $stmt->bind_param('sss', $_POST['EmailID'], $_POST['SLA'], $_POST['Password']); $stmt->execute(); $result = $stmt->get_result(); 

Я получаю сообщение об ошибке на последней строке: Вызов неопределенного метода mysqli_stmt :: get_result ()

Вот код для conn.php:

 define('SERVER', 'localhost'); define('USER', 'root'); define('PASS', 'xxxx'); define('DB', 'xxxx'); class Connection{ /** * @var Resource */ var $mysqli = null; function __construct(){ try{ if(!$this->mysqli){ $this->mysqli = new MySQLi(SERVER, USER, PASS, DB); if(!$this->mysqli) throw new Exception('Could not create connection using MySQLi', 'NO_CONNECTION'); } } catch(Exception $ex){ echo "ERROR: ".$e->getMessage(); } } } 

Если я напишу эту строку:

 if(!stmt) echo 'Statement prepared'; else echo 'Statement NOT prepared'; 

Он печатает «Заявление НЕ подготовлено» . Если я запускаю запрос непосредственно в замене IDE? знаки со значениями, он отлично работает. Обратите внимание, что объект $ conn отлично работает в других запросах проекта.

Любая помощь, пожалуйста …

Пожалуйста, прочтите примечания пользователя для этого метода:

http://php.net/manual/en/mysqli-stmt.get-result.php

Для этого требуется драйвер mysqlnd … если он не установлен на вашем веб-пространстве, вам придется работать с BIND_RESULT & FETCH!

https://secure.php.net/manual/en/mysqli-stmt.bind-result.php

https://secure.php.net/manual/en/mysqli-stmt.fetch.php

Поэтому, если драйвер MySQL Native Driver (mysqlnd) недоступен и, следовательно, использует bind_result и fetch вместо get_result , код становится:

 include 'conn.php'; $conn = new Connection(); $query = 'SELECT EmailVerified, Blocked FROM users WHERE Email = ? AND SLA = ? AND `Password` = ?'; $stmt = $conn->mysqli->prepare($query); $stmt->bind_param('sss', $_POST['EmailID'], $_POST['SLA'], $_POST['Password']); $stmt->execute(); $stmt->bind_result($EmailVerified, $Blocked); while ($stmt->fetch()) { /* Use $EmailVerified and $Blocked */ } $stmt->close(); $conn->mysqli->close(); 

В вашей системе отсутствует драйвер mysqlnd!

Если вы можете установить новые пакеты на своем (Debian / Ubuntu) сервере, установите драйвер:

 sudo apt-get install php5-mysqlnd 

а затем перезапустите веб-сервер:

 sudo /etc/init.d/apache2 restart 

для тех, кто ищет альтернативу $ result = stmt-> get_result () Я сделал эту функцию, которая позволяет вам имитировать $ result-> fetch_assoc (), но напрямую используя объект stmt:

 function fetchAssocStatement($stmt) { if($stmt->num_rows>0) { $result = array(); $md = $stmt->result_metadata(); $params = array(); while($field = $md->fetch_field()) { $params[] = &$result[$field->name]; } call_user_func_array(array($stmt, 'bind_result'), $params); if($stmt->fetch()) return $result; } return null; } 

поскольку вы можете видеть, что он создает массив и извлекает его с данными строки, поскольку он использует внутреннюю структуру $ stmt-> fetch (), вы можете вызвать его так же, как вы бы вызвали mysqli_result :: fetch_assoc (просто убедитесь, что объект $ stmt открыто и результат сохраняется):

 //mysqliConnection is your mysqli connection object if($stmt = $mysqli_connection->prepare($query)) { $stmt->execute(); $stmt->store_result(); while($assoc_array = fetchAssocStatement($stmt)) { //do your magic } $stmt->close(); } 

надеюсь это поможет.

Я знаю, что на это уже был дан ответ, какова фактическая проблема, однако я хочу предложить простой обходной путь.

Я хотел использовать метод get_results (), но у меня не было драйвера, и я не где-то, я могу добавить его. Итак, прежде чем я позвонил

 $stmt->bind_results($var1,$var2,$var3,$var4...etc); 

Я создал пустой массив, а затем просто привязал результаты как ключи в этом массиве:

 $result = array(); $stmt->bind_results($result['var1'],$result['var2'],$result['var3'],$result['var4']...etc); 

так что эти результаты могут быть легко переданы в методы или переданы объекту для дальнейшего использования.

Надеюсь, это поможет любому, кто хочет сделать что-то подобное.

Вот моя альтернатива. Он объектно-ориентирован и больше похож на вещи mysql / mysqli.

 class MMySqliStmt{ private $stmt; private $row; public function __construct($stmt){ $this->stmt = $stmt; $md = $stmt->result_metadata(); $params = array(); while($field = $md->fetch_field()) { $params[] = &$this->row[$field->name]; } call_user_func_array(array($stmt, 'bind_result'), $params) or die('Sql Error'); } public function fetch_array(){ if($this->stmt->fetch()){ $result = array(); foreach($this->row as $k => $v){ $result[$k] = $v; } return $result; }else{ return false; } } public function free(){ $this->stmt->close(); } } 

Применение:

 $stmt = $conn->prepare($str); //...bind_param... and so on if(!$stmt->execute())die('Mysql Query(Execute) Error : '.$str); $result = new MMySqliStmt($stmt); while($row = $result->fetch_array()){ array_push($arr, $row); //for example, use $row['id'] } $result->free(); //for example, use the $arr 

Я понимаю, что прошло какое-то время, так как в этом вопросе была новая деятельность. Но, как комментировали другие плакаты – get_result() теперь доступен только на PHP, установив собственный драйвер MySQL (mysqlnd), и в некоторых случаях может оказаться невозможным или желательным установить mysqlnd. Итак, я подумал, что было бы полезно опубликовать этот ответ с информацией о том, как получить функциональность, get_result() предлагает get_result() без использования get_result() .

get_result() часто / комбинируется с fetch_array() чтобы fetch_array() результирующий набор и сохранить значения из каждой строки результирующего набора в числовом индексированном или ассоциативном массиве. Например, приведенный ниже код использует get_result () с fetch_array () для циклического преобразования в результирующий набор, сохраняя значения из каждой строки в числовом индексированном массиве $ data []:

 $c=1000; $sql="select account_id, username from accounts where account_id<?"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('i', $c); $stmt->execute(); $result = $stmt->get_result(); while($data = $result->fetch_array(MYSQLI_NUM)) { print $data[0] . ', ' . $data[1] . "<BR>\n"; } 

Однако, если get_result() недоступен (поскольку mysqlnd не установлен), это приводит к проблеме сохранения значений из каждой строки результирующего набора в массиве без использования get_result() . Или, как переносить устаревший код, который использует get_result() для запуска без него (например, с помощью bind_result() ) – при этом как можно меньше воздействует на остальную часть кода.

Оказывается, что сохранение значений из каждой строки в массиве с числовой индексацией не так прямолинейно, используя bind_result() . bind_result() ожидает список скалярных переменных (а не массив). Таким образом, требуется некоторое выполнение, чтобы сохранить значения из каждой строки набора результатов в массиве.

Конечно, код можно легко изменить следующим образом:

 $c=1000; $sql="select account_id, username from accounts where account_id<?"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('i', $c); $stmt->execute(); $stmt->bind_result($data[0], $data[1]); while ($stmt->fetch()) { print $data[0] . ', ' . $data[1] . "<BR>\n"; } 

Но для этого требуется явно указать $ data [0], $ data [1] и т. Д. Индивидуально в вызове bind_result() , что не является идеальным. Мы хотим, чтобы решение, которое не требует, чтобы явным образом перечислил $ data [0], $ data [1], … $ data [N-1] (где N – количество полей в инструкции select) в вызове bind_results() . Если мы переносим устаревшее приложение с большим количеством запросов, и каждый запрос может содержать другое количество полей в предложении select , миграция будет очень трудоемкой и подверженной ошибкам, если мы используем такое решение, как одно выше.

В идеале нам нужен фрагмент кода «замены замены», чтобы заменить только строку, содержащую get_result() и цикл while () на следующей строке. Код замены должен иметь ту же функцию, что и код, который он заменяет, не затрагивая ни одну из строк раньше или любую из строк после – включая строки внутри цикла while (). В идеале мы хотим, чтобы код замены был как можно более компактным, и мы не хотим, чтобы код замены был заменен на количество полей в предложении select запроса.

Поиск в Интернете я нашел ряд решений, которые используют bind_param() с помощью call_user_func_array() (например, динамически связывают параметры mysqli_stmt, а затем связывают результат (PHP) ), но большинство найденных решений в конечном итоге приводят к сохранению результатов в ассоциативном массиве, а не в численном индексированном массиве, и многие из этих решений были не такими компактными, как я хотел бы и / или не были бы пригодны в качестве «замены для замены». Однако из примеров, которые я нашел, я смог собрать это решение, которое соответствует законопроекту:

 $c=1000; $sql="select account_id, username from accounts where account_id<?"; $stmt = $mysqli->prepare($sql); $stmt->bind_param('i', $c); $stmt->execute(); $data=array(); for ($i=0;$i<$mysqli->field_count;$i++) { $var = $i; $$var = null; $data[$var] = &$$var; } call_user_func_array(array($stmt,'bind_result'), $data); while ($stmt->fetch()) { print $data[0] . ', ' . $data[1] . "<BR>\n"; } 

Конечно, цикл for () может быть свернут в одну строку, чтобы сделать его более компактным.

Я надеюсь, что это поможет любому, кто ищет решение, используя bind_result() для хранения значений из каждой строки в массиве с числовой индексацией и / или ищет способ переноса устаревшего кода с помощью get_result() . Комментарии приветствуются.