MySQL 整数字段在 PHP 中作为字符串返回

我在 MySQL 数据库中有一个表字段:

userid INT(11)

所以我用这个问题把它叫到我的页面上:

"SELECT userid FROM DB WHERE name='john'"

然后,为了处理结果,我这样做了:

$row=$result->fetch_assoc();


$id=$row['userid'];

如果我这么做了:

echo gettype($id);

我得到一个字符串,这不应该是一个整数吗?

136642 次浏览

当您使用 PHP 从 MySQL 数据库中选择数据时,数据类型将始终转换为字符串。您可以使用以下代码将其转换回整数:

$id = (int) $row['userid'];

Or by using the function intval():

$id = intval($row['userid']);

不管表中定义的数据类型如何,PHP 的 MySQL 驱动程序始终将行值作为字符串提供。

您需要将 ID 强制转换为 int 类型。

$row = $result->fetch_assoc();
$id = (int) $row['userid'];

在我的项目中,我通常使用一个外部函数来“过滤”用 mysql_fetch_assoc检索到的数据。

您可以重命名表中的字段,以便直观地理解存储的数据类型。

例如,您可以为每个数字字段添加一个特殊的后缀: 如果 userid是一个 INT(11)你可以重命名它 userid_i或者如果它是一个 UNSIGNED INT(11)你可以重命名 userid_u。 此时,您可以编写一个简单的 PHP 函数,将关联数组作为输入接收(用 mysql_fetch_assoc检索) ,并将强制转换应用于存储在这些特殊“键”中的“值”。

你可以用..。

  1. Mysql _ get _ field ()
  2. Mysqli _ result: : fetch _ field _ direct or
  3. PDOStatement: : getColumnMeta ()

取决于你想用哪个分机。不推荐使用第一种方法,因为 mysql 扩展已被弃用。第三种仍处于试验阶段。

这些超链接中的注释很好地解释了如何将类型从普通的旧字符串设置为数据库中的原始类型。

一些框架也对此进行了抽象(CodeIgniter 提供了 $this->db->field_data())。

您还可以进行猜测——比如在结果行中进行循环,并在每一行上使用 Is _ numeric ():

foreach($result as &$row){
foreach($row as &$value){
if(is_numeric($value)){
$value = (int) $value;
}
}
}

这会把任何看起来像数字的东西变成一... 绝对不是完美的。

如果使用准备好的语句,则在适当的地方类型将为 int。这段代码返回一个行数组,其中每一行都是一个关联数组。比如对所有行调用 fetch_assoc(),但是保留类型信息。

function dbQuery($sql) {
global $mysqli;


$stmt = $mysqli->prepare($sql);
$stmt->execute();
$stmt->store_result();


$meta = $stmt->result_metadata();
$params = array();
$row = array();


while ($field = $meta->fetch_field()) {
$params[] = &$row[$field->name];
}


call_user_func_array(array($stmt, 'bind_result'), $params);


while ($stmt->fetch()) {
$tmp = array();
foreach ($row as $key => $val) {
$tmp[$key] = $val;
}
$ret[] = $tmp;
}


$meta->free();
$stmt->close();


return $ret;
}

我的解决方案是传递查询结果 $rs,并获得一个 assoc 数组,其中包含转换后的数据作为返回值:

function cast_query_results($rs) {
$fields = mysqli_fetch_fields($rs);
$data = array();
$types = array();
foreach($fields as $field) {
switch($field->type) {
case 3:
$types[$field->name] = 'int';
break;
case 4:
$types[$field->name] = 'float';
break;
default:
$types[$field->name] = 'string';
break;
}
}
while($row=mysqli_fetch_assoc($rs)) array_push($data,$row);
for($i=0;$i<count($data);$i++) {
foreach($types as $name => $type) {
settype($data[$i][$name], $type);
}
}
return $data;
}

示例用法:

$dbconn = mysqli_connect('localhost','user','passwd','tablename');
$rs = mysqli_query($dbconn, "SELECT * FROM Matches");
$matches = cast_query_results($rs);
// $matches is now a assoc array of rows properly casted to ints/floats/strings

对 php 使用 mysqlnd (本机驱动程序)。

如果你在使用 Ubuntu:

sudo apt-get install php5-mysqlnd
sudo service apache2 restart

如果你在森托斯:

sudo yum install php-mysqlnd
sudo service httpd restart

本机驱动程序适当地返回整数类型。

正如@Jeroen 所指出的,这种方法只适用于 PDO。
正如@LarsMoelleken 所指出的,如果您还将 MYSQLI _ OPT _ INT _ AND _ FLOAT _ NATIVE 选项设置为 true,则此方法将与 MYSQLI 一起工作。

例如:

$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, TRUE);

我喜欢 Chad 的回答,尤其是当查询结果将在浏览器中传递到 javascript 时。Javascript 干净利落地将类似数字的实体作为数字处理,但是需要额外的工作来将类似数字的实体作为字符串处理。即必须对它们使用 parseInt 或 parseFloat。

在 Chad 的解决方案的基础上,我使用了它,它通常正是我所需要的,并且创建了可以用 JSON 编码的结构,以便于在 javascript 中处理。

while ($row = $result->fetch_assoc()) {
// convert numeric looking things to numbers for javascript
foreach ($row as &$val) {
if (is_numeric($val))
$val = $val + 0;
}
}

将数字字符串添加到0会在 PHP 中生成一个数字类型,并正确标识该类型,这样浮点数就不会被截断为整数。

MySQL 有许多其他语言的驱动程序,将数据转换为字符串“标准化”数据,然后由用户将值转换为 int 或其他类型

我发现的最简单的解决方案:

您可以强制 json _ encode 对看起来像数字的值使用实际的数字:

json_encode($data, JSON_NUMERIC_CHECK)

(从 PHP 5.3.3开始)。

或者您可以将 ID 强制转换为 int 类型。

$row = $result->fetch_assoc();
$id = (int) $row['userid'];

在我的情况下,已经安装了 mysqlnd.so扩展。但我没有 pdo_mysqlnd.so。因此,用 pdo_mysqlnd.so代替 pdo_mysql.so解决了这个问题。

当连接上的 PDO::ATTR_EMULATE_PREPARES设置为 true时会发生这种情况。

不过要小心,将其设置为 false不允许多次使用参数。我相信它还会影响返回的错误消息的质量。

我喜欢 策划者的技巧,但编码可以更简单:

function cast_query_results($result): array
{
if ($result === false)
return null;


$data = array();
$fields = $result->fetch_fields();
while ($row = $result->fetch_assoc()) {
foreach ($fields as $field) {
$fieldName = $field->name;
$fieldValue = $row[$fieldName];
if (!is_null($fieldValue))
switch ($field->type) {
case 3:
$row[$fieldName] = (int)$fieldValue;
break;
case 4:
$row[$fieldName] = (float)$fieldValue;
break;
// Add other type conversions as desired.
// Strings are already strings, so don't need to be touched.
}
}
array_push($data, $row);
}


return $data;
}

我还添加了查询返回 false 而不是结果集的检查。
并检查具有空值的字段的行。
如果想要的类型是一个字符串,我不会在它上面浪费任何时间——它已经是一个字符串了。


在大多数 php 代码中我不会费心使用这个; 我只是依赖于 php 的自动类型转换。但是如果要查询大量数据,然后执行算术计算,那么预先强制转换为最佳类型是明智的。

$mysqli->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, TRUE);

试试这个,对我管用。

仅限 mysqlnd:

 mysqli_options($conn, MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true);

否则:

  $row = $result->fetch_assoc();


while ($field = $result->fetch_field()) {
switch (true) {
case (preg_match('#^(float|double|decimal)#', $field->type)):
$row[$field->name] = (float)$row[$field->name];
break;
case (preg_match('#^(bit|(tiny|small|medium|big)?int)#', $field->type)):
$row[$field->name] = (int)$row[$field->name];
break;
default:
$row[$field->name] = $row[$field->name];
break;
}
}

如果您使用类/对象来存储数据库数据,您可以输入 cast 它的属性,这样就可以将它转换为正确的类型:

<?php
class User
{
public int $id; // use type casting in class definition
}
  

$user1 = new User();
$user1->id = $row['userid'];
echo gettype($user1->id); // integer
?>

注意: 我想指出的是,上面的 Charlie 解决方案在我的 Windows 环境中工作,但是当我试图在 linux 服务器上部署项目时,将 PDO: : ATTR _ EMULATE _ PREPARES 更改为 false 不起作用。我还是用字符串代替数字。