PHP & MySQL: zerofill is lost when using mysqli->prepare()

故事扮演 提交于 2019-12-14 03:23:00

问题


Using: MySQL 5.1 + PHP 5.3.5

MySQL:

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

I get the expected result when using:

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

But not when I use prepared statement:

$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

When trying the prepared statement directly in the MySQL console, it shows as expected (it is not MySQL).

According to PHP mysqli_stmt::bind_result documentation I found this:

Depending on column types bound variables can silently change to the corresponding PHP type.

I need to show the number with the trailing zeros WITHOUT having to do it in a later step. There are so many fields with zerofill and the process is practically automated from the data to the screen, so trying to fix this after this code, will require mayor changes.

Any hint of how to solve this problem is welcome.


回答1:


The zerofill gets lost, because mysqli knows that the column is of type integer and so the type of the php variable becomes also int and so the leading zeros get lost.

This seems only to happen when you use prepared statements with mysqli (PDO seems not to have this behavior).

To prevent mysqli the type of the variable to integer you have to change the type in MySQL to something that is returned as a string.

There are two ways:

  1. CAST(intCol AS CHAR) casts the integer including the leading zeros to a string.
  2. Using the zerofilled integer in a string context, e.g. CONCAT(intCol, "").

Notice: If you use this value in an HTML5 input field of type number, this will also strip off leading zeros (at least in some browsers). To solve this problem have a look at this answer.




回答2:


Temporally, I solved it adding these lines:

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;
}  

Still I hope someone can show me a better way to solve it.




回答3:


Another solution was to specify the field as decimal(6,0). For some reason it works as expected (no changes to the code required).



来源:https://stackoverflow.com/questions/6825106/php-mysql-zerofill-is-lost-when-using-mysqli-prepare

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!