В последнее время я наткнулся на ошибку в lib, которая работала нормально, и я буду проклят, если смогу выяснить, где она находится.
Ниже приведен пример кода, и я извиняюсь за материал отладки, который находится внутри него, но я пытаюсь заставить его работать.
Проблема заключается в том, что $ temp – это массив с правильным ключом (имя столбца), но все значения NULL.
Я думаю, проблема кроется в
call_user_func_array(array($query, 'bind_result'), $params);
бит, но я не могу обернуть вокруг него голову.
public function fetchRows(){ error_reporting(E_ALL+E_NOTICE); $args = func_get_args(); $sql = array_shift($args); traceVar($sql, "Query"); $colTypes = array_shift($args); if (!$query = $this->prepare($sql, $colTypes)) { die('Please check your sql statement : unable to prepare'); } if (count($args)){ traceVar($args,'Binding params with'); call_user_func_array(array($query,'bindParam'), $args); } $query->execute(); $meta = $query->result_metadata(); while ($field = $meta->fetch_field()) { $params[] = &$row[$field->name]; } traceVar($params,'Binding results with'); call_user_func_array(array($query, 'bind_result'), $params); while ($query->fetch()) { traceVar($row,'After fetch'); $temp = array(); foreach($row as $key => $val) { $temp[$key] = $val; } $result[] = $temp; } $meta->free(); $query->close(); //self::close_db_conn(); return $result; }
Код, который вы предоставили, работает для меня.
Функция call_user_func_array(...)
просто вызывает методы bindParam
или bind_result
объекта $query
с заданным массивом, как если бы вы предоставили каждый элемент массива как аргумент метода.
Вы можете проверить SQL-запрос, с которым вы столкнулись, с кодом ниже. Я немного переписал его, чтобы сделать его полностью проверяемым, так как исходный код зависит от класса оператора на вашем уровне абстракции.
<?php $db_host = 'localhost'; $db_user = 'username'; $db_pass = 'password'; $db_name = 'database'; $mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name); print_r(fetchRows('SELECT something from some_table WHERE some_id = ?', 'i', 1)); function traceVar($a, $b) { print_r(array($b => $a)); } function fetchRows(){ error_reporting(E_ALL+E_NOTICE); $args = func_get_args(); $sql = array_shift($args); traceVar($sql, "Query"); // Keep the column types for bind_param. // $colTypes = array_shift($args); // Column types were originally passed here as a second // argument, and stored in the statement object, I suppose. if (!$query = $GLOBALS['mysqli']->prepare($sql)){ //, $colTypes)) { die('Please check your sql statement : unable to prepare'); } if (count($args)){ traceVar($args,'Binding params with'); // Just a quick hack to pass references in order to // avoid errors. foreach ($args as &$v) { $v = &$v; } // Replace the bindParam function of the original // abstraction layer. call_user_func_array(array($query,'bind_param'), $args); //'bindParam'), $args); } $query->execute(); $meta = $query->result_metadata(); while ($field = $meta->fetch_field()) { $params[] = &$row[$field->name]; } traceVar($params,'Binding results with'); call_user_func_array(array($query, 'bind_result'), $params); while ($query->fetch()) { traceVar($row,'After fetch'); $temp = array(); foreach($row as $key => $val) { $temp[$key] = $val; } $result[] = $temp; } $meta->free(); $query->close(); //self::close_db_conn(); return $result; }
Если бы мы могли выбрать сервер при запуске, мы могли бы использовать модуль php-mysqlnd вместо модуля php-mysql для PHP. (Или некоторые из вас, возможно, уже используют его, запустите «phpinfo ();» и выполните поиск «mysqlnd»):
public function fetchRows(){ ... $query->execute(); $res = $query->get_result(); while (($row = $res->fetch_assoc())) $result[] = $row; return $result; } }
Это кажется мне проще.