PHP& MySQL:zerofill在使用mysqli-> prepare()时丢失了

时间:2011-07-26 04:01:44

标签: mysql mysqli prepared-statement zerofill

使用:     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类型。

我需要使用尾随零来显示数字,而不必在后面的步骤中执行此操作。 zerofill有很多字段,从数据到屏幕实际上是自动化的过程,因此在此代码之后尝试修复此问题将需要更改市长。

欢迎任何有关如何解决此问题的提示。

3 个答案:

答案 0 :(得分:1)

zerofill迷路了,因为mysqli知道列的类型是整数,因此php变量的类型也变为int,因此前导零会丢失。

这似乎只有在你使用mysqli准备好的语句时才会发生(PDO似乎没有这种行为)。

为了防止mysqli变量的类型为整数,你必须将MySQL中的类型更改为以字符串形式返回的内容。

有两种方法:

  1. CAST(intCol AS CHAR)将包含前导零的整数强制转换为字符串。
  2. 在字符串上下文中使用零填充整数,例如CONCAT(intCol, "")
  3. 注意:如果在类型为number的HTML5输入字段中使用此值,则还会删除前导零(至少在某些浏览器中)。要解决此问题,请查看this answer

答案 1 :(得分:0)

暂时,我解决了这些问题:

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

我仍然希望有人能告诉我更好的解决方法。

答案 2 :(得分:0)

另一个解决方案是将字段指定为十进制(6,0)。由于某种原因,它按预期工作(不需要更改代码)。