PHP и MySQL: zerofill теряется при использовании mysqli->prepare()

Использование: MySQL 5.1 + PHP 5.3.5

MySQL:

id in "table" is defined as: mediumint(6) zerofill not null

Я получаю ожидаемый результат при использовании:

$mysqli->query("SELECT id FROM table WHERE id = 1");
while($row = $ret->fetch_array(MYSQLI_ASSOC)) $arr[] = $row;
>>> $arr[0]["id"] = 000001

Но не тогда, когда я использую подготовленное утверждение:

$ret = $mysqli->prepare("SELECT id FROM table WHERE id = ?");
call_user_func_array(array($ret,"bind_param"),array("i",1));
$ret->execute();
$ret->store_result();
$meta = $ret->result_metadata();
$fields = $meta->fetch_fields();
$cols = array(); $data = array();
foreach($fields as $field) $cols[] = &$data[$field->name];
call_user_func_array(array($ret, 'bind_result'), $cols);
while($ret->fetch()) {
    $row = array();
    foreach($data as $key => $val) $row[$key] = $val;
    $arr[] = $row;
}
>>> $arr[0]["id"] = 1

При попытке подготовить оператор непосредственно в консоли MySQL, он показывает, как ожидалось (это не MySQL).

Согласно документации PHP mysqli_stmt:: bind_result я нашел это:

В зависимости от типов столбцов связанные переменные могут молча меняться на соответствующий тип PHP.

Мне нужно показать число с конечными нулями, БЕЗ необходимости делать это на более позднем этапе. С нулевым заполнением есть так много полей, и процесс практически автоматизирован от данных до экрана, поэтому попытка исправить это после этого кода потребует изменений мэра.

Любой намек на решение этой проблемы приветствуется.

3 ответа

Решение

Другим решением было указать поле как десятичное (6,0). По некоторым причинам это работает как ожидалось (никаких изменений в коде не требуется).

Zerofill теряется, потому что mysqli знает, что столбец имеет тип integer, и поэтому тип переменной php становится также int, и поэтому ведущие нули теряются.

Кажется, это происходит только тогда, когда вы используете подготовленные операторы с mysqli (PDO, похоже, не имеет такого поведения).

Чтобы предотвратить mysqli, тип переменной на целое, вы должны изменить тип в MySQL на что-то, что возвращается в виде строки.

Есть два способа:

  1. CAST(intCol AS CHAR) преобразует целое число, включая ведущие нули, в строку.
  2. Использование целого числа с нулевым заполнением в строковом контексте, например CONCAT(intCol, ""),

Примечание: если вы используете это значение в поле ввода HTML5 типа numberэто также удалит начальные нули (по крайней мере, в некоторых браузерах). Чтобы решить эту проблему, взгляните на этот ответ.

Временно я решил это, добавив следующие строки:

define("ZEROFILL_FLAG",64);
$zeros = array();
foreach($fields as $field) {
    $zeros[$field->name] = $field->flags & ZEROFILL_FLAG ? $field->length : 0;
    $cols[] = &$data[$field->name];
}   
call_user_func_array(array($ret, 'bind_result'), $cols);
while($ret->fetch()) {
    $row = array();
    foreach($data as $key => $val) {
        $row[$key] = $zeros[$key] > 0 ? sprintf('%0'.$zeros[$key].'s', $val) : $val;
    }   
    $arr[] = $row;
}  

Тем не менее, я надеюсь, что кто-то может показать мне лучший способ решить эту проблему.

Другие вопросы по тегам