Вызов неопределенного метода 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 ()
вот код для подкл.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 отлично работает в других запросах проект.
любая помощь, пожалуйста.......
9 ответов:
пожалуйста, прочитайте Примечания пользователя для этого метода:
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
поэтому, если драйвер 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-based), установите драйвер:
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()
- это/часто в сочетании с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
предложение, миграция будет очень трудоемкой и склонной к ошибкам, если мы используем решение, подобное приведенному выше.в идеале, мы хотим фрагмент кода "drop-in replacement" - чтобы заменить только строку, содержащую
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()
. Комментарии приветствуются.
я написал две простые функции, которые дают ту же функциональность, что и
$stmt->get_result();
, но они не требуют драйвера mysqlnd.вы просто заменить
$result = $stmt->get_result();
С$fields = bindAll($stmt);
и
$row= $stmt->get_result();
С$row = fetchRowAssoc($stmt, $fields);
.(чтобы получить количество возвращаемых строк, вы можете использовать
$stmt->num_rows
.)вы просто поместите эти два функции я написал где-то в вашем PHP-скрипт. (например, прямо внизу)
function bindAll($stmt) { $meta = $stmt->result_metadata(); $fields = array(); $fieldRefs = array(); while ($field = $meta->fetch_field()) { $fields[$field->name] = ""; $fieldRefs[] = &$fields[$field->name]; } call_user_func_array(array($stmt, 'bind_result'), $fieldRefs); $stmt->store_result(); //var_dump($fields); return $fields; } function fetchRowAssoc($stmt, &$fields) { if ($stmt->fetch()) { return $fields; } return false; }
как это работает:
мой код использует
$stmt->result_metadata();
функции, чтобы выяснить, сколько и какие поля возвращаются, а затем автоматически связывает полученные результаты с предварительно созданных ссылок. Работает как шарм!