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 на что-то, что возвращается в виде строки.
Есть два способа:
CAST(intCol AS CHAR)
преобразует целое число, включая ведущие нули, в строку.- Использование целого числа с нулевым заполнением в строковом контексте, например
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;
}
Тем не менее, я надеюсь, что кто-то может показать мне лучший способ решить эту проблему.