Каждый, кто ответил на этот вопрос до сих пор, абсолютно прав - read()
перемещается по файлу, поэтому после того, как вы его вызвали, вы не можете его снова называть.
Что я буду add - это то, что в вашем конкретном случае вам не нужно искать назад или снова открывать файл, вы можете просто сохранить текст, который вы прочитали в локальной переменной, и использовать его дважды или столько раз, сколько вам нравится, в вашей программе:
f = f.open()
text = f.read() # read the file into a local variable
# get the year
match = re.search(r'Popularity in (\d+)', text)
if match:
print match.group(1)
# get all the names
matches = re.findall(r'<td>(\d+)</td><td>(\w+)</td><td>(\w+)</td>', text)
if matches:
# matches will now not always be None
Пожалуйста, прочтите примечания пользователя для этого метода:
http://php.net/manual/en/mysqli-stmt.get-result.php
Требуется драйвер mysqlnd ... если он не установлен на вашем веб-пространстве, вам придется работать с BIND_RESULT & amp; FETCH!
https://secure.php.net/manual/en/mysqli-stmt.bind-result.php
Я получал эту же ошибку на своем сервере - PHP 7.0 с расширением mysqlnd уже включен.
Решение было для меня (благодаря этой странице ) было отменять выбор mysqli и выберите nd_mysqli.
Примечание. Вы можете иметь доступ к селектору расширений в вашей cPanel. (Я получаю доступ к моей версии через опцию «Выбрать версию 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();
$EmailVerfied
создается вызовом bind_result()
.
– AbraCadaver
24 January 2018 в 19:54
В вашей системе отсутствует драйвер mysqlnd!
Если вы можете установить новые пакеты на своем (на сервере Debian / Ubuntu), установите драйвер:
sudo apt-get install php5-mysqlnd
, а затем перезапустите веб-сервер:
sudo /etc/init.d/apache2 restart
Я понимаю, что прошло какое-то время, поскольку в этом вопросе была новая деятельность. Но, как комментировали другие плакаты, 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
, миграция будет очень трудоемкой и подверженной ошибкам, если мы используем такое решение, как
В идеале нам нужен фрагмент кода «замены замены», чтобы заменить только строку, содержащую функцию 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()
, Комментарии приветствуются.
Вот моя альтернатива. Это объектно-ориентированное и больше похоже на вещи 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
для тех, кто ищет альтернативу $ 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();
}
надеюсь, что это поможет.
$statement->store_result();
, почему бы просто не включить ее в функцию?
– InsanityOnABun
18 August 2016 в 20:01
Я знаю, что на это уже был дан ответ, какова фактическая проблема, однако я хочу предложить простой обходной путь.
Я хотел использовать метод get_results (), однако у меня не было драйвера , и я не где-то, я могу добавить это. Итак, прежде чем я позвонил
$stmt->bind_results($var1,$var2,$var3,$var4...etc);
, я создал пустой массив и просто привязал результаты как ключи в этом массиве:
$result = array();
$stmt->bind_results($result['var1'],$result['var2'],$result['var3'],$result['var4']...etc);
, чтобы эти результаты могли быть легко переданы в методы или переданы объекту для дальнейшего использования.
Надеюсь, это поможет любому, кто хочет сделать что-то подобное.
Я написал две простые функции, которые дают ту же функциональность, что и $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();
, чтобы выяснить, сколько и какие поля возвращаются, а затем автоматически привязывает полученные результаты к предварительно созданным ссылкам. Работает как очарование!
mysqli_stmt::get_result()
доступен только на PHP версии 5.0 или выше. – Raptor 28 November 2012 в 15:54php_mysqli_mysqlnd.dll
? У меня было быphp_mysqli.dll
в моей папкеext
. – Pacerier 29 June 2015 в 10:07