PHP + PDO + MySQL:我如何从PHP中返回整数和数字列作为整数和数字?

ste*_*ank 76 php mysql macos ubuntu pdo

我已经在Stack Overflow上重复了几次这个问题,但是没有一个能够充分探索这个问题(或者至少以一种对我有帮助的方式)

问题是数据库查询应该在PHP中为整数列返回整数数据类型.相反,查询将每列作为字符串类型返回.

我确保"PDO :: ATTR_STRINGIFY_FETCHES"为false,以确保结果不会被转换为字符串.

我见过的答案:

  • 它无法完成
    • 不,它正在Mac OS X上安装PHP/MySQL
  • 在代码中输入所有值
    • 不,我不会这样做
  • 不要担心,PHP是松散的类型
    • 我的数据输出为JSON并被许多其他服务使用,有些需要正确格式的数据

根据我的研究,我了解这是一个驱动程序实现问题.

许多消息来源声称MySQL本机驱动程序不支持返回数字类型.这似乎不正确,因为它适用于Mac OS X.除非他们的意思是" Linux上的MySQL本机驱动程序不支持该功能".

这意味着我在Mac OS X上安装的驱动程序/环境有一些特殊之处.我一直在尝试识别差异以便应用修复,但我受限于我对如何检查这些内容的了解.

差异:

  • OS X上的PHP是通过Home Brew编译和安装的
  • Ubuntu上的PHP是通过"apt-get install php5-dev"安装的
  • OS X上的PHP连接到也在OS X上运行的MySQL服务器
    • 服务器版本:5.1.71-log源分发
  • Ubuntu上的PHP连接到Rackspace云数据库
    • 服务器版本:5.1.66-0 + squeeze1(Debian)

Ubuntu环境

  • 版本:10.04.1
  • PHP 5.4.21-1 + debphp.org~lucid + 1(cli)(内置:2013年10月21日08:14:37)
  • php -i

    PDO_MYSQL

    用于MySQL的PDO驱动程序=>已启用客户端API版本=> 5.1.72

Mac OS X环境

  • 10.7.5
  • PHP 5.4.16(cli)(内置:2013年8月22日09:05:58)
  • php -i

    PDO_MYSQL

    用于MySQL的PDO驱动程序=>启用客户端API版本=> mysqlnd 5.0.10 - 20111026 - $ Id:e707c415db32080b3752b232487a435ee0372157 $

使用PDO标志

PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES => false,
Run Code Online (Sandbox Code Playgroud)

任何帮助和专业知识将不胜感激:)如果我找到答案,我肯定会回到这里.

ste*_*ank 113

解决方案是确保您使用php 的mysqlnd驱动程序.

你怎么知道你没有使用mysqlnd?

查看时php -i,不会提及"mysqlnd".该pdo_mysql部分将具有以下内容:

pdo_mysql

PDO Driver for MySQL => enabled Client API version => 5.1.72
Run Code Online (Sandbox Code Playgroud)

你是如何安装的?

L/A/M/P的大多数安装指南apt-get install php5-mysql都有建议,但MySQL的本机驱动程序是由不同的软件包安装的:php5-mysqlnd.我发现这可用于ppa:ondrej/php5-oldstable.

要切换到新驱动程序(在Ubuntu上):

  • 删除旧驱动程序:
    apt-get remove php5-mysql
  • 安装新驱动程序:
    apt-get install php5-mysqlnd
  • 重启apache2:
    service apache2 restart

如何检查驱动程序是否正在使用?

现在php -i将在以下pdo_mysql部分中明确提到"mysqlnd" :

pdo_mysql

PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.10 - 20111026 - $Id:      e707c415db32080b3752b232487a435ee0372157 $
Run Code Online (Sandbox Code Playgroud)

PDO设置

确保PDO::ATTR_EMULATE_PREPARESfalse(检查您的默认值或设置它):
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

确保PDO::ATTR_STRINGIFY_FETCHESfalse(检查您的默认值或设置它):
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

返回值

  • 浮点类型(FLOAT,DOUBLE)作为PHP浮点数返回.
  • 整数类型(INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT†)作为PHP整数返回.
  • 定点类型(DECIMAL,NUMERIC)作为字符串返回.

†值大于64位signed int(9223372036854775807)的BIGINT将作为字符串返回(或32位系统上的32位)

    object(stdClass)[915]
      public 'integer_col' => int 1
      public 'double_col' => float 1.55
      public 'float_col' => float 1.5
      public 'decimal_col' => string '1.20' (length=4)
      public 'bigint_col' => string '18446744073709551615' (length=20)
Run Code Online (Sandbox Code Playgroud)

  • 另请注意,PDO :: ATTR_STRINGIFY_FETCHES与它无关 - 我试过它对结果没有影响,并在[this post](http://stackoverflow.com/questions/1197005/how-to-get-来自mysql-using-pdo的数字类型用户@Josh Davis说这与MySQL无关. (4认同)
  • 请注意,即使启用了此版本的mysqlnd,DECIMALS仍将作为字符串发送...(虽然FLOATS将作为浮点数返回!):/来源:我测试了它. (3认同)
  • @pere这是正确的行为.DECIMAL不是数字类型.它是数字的字符串格式.所以你可以返回:`0.30`为"0.30"`而不是`0.3`.十进制用于此...所以这是正确的行为 (3认同)

Cra*_*obs 5

这个被接受的答案是有效的,似乎是这个问题在谷歌上最受欢迎的答案。我的问题是我需要将应用程序部署到多个环境中,而且我并不总是能够安装正确的驱动程序,而且我需要将小数设为数字,而不是字符串。所以我创建了一个例程来在 JSON 编码之前输入大小写,很容易修改以适应。这有点像从轨道上炸毁它。

首先,使用“show columns from”从表中获取列。mysql 查询“SHOW COLUMNS FROM table like 'colmunname'”:问题

$query = 'SHOW COLUMNS FROM ' . $table; //run with mysqli or PDO 
Run Code Online (Sandbox Code Playgroud)

然后将类型放入由列名索引的数组中,以便于迭代。假设来自 show columns 的结果集位于名为 $columns_from_table 的变量中。http://php.net/manual/en/function.array-column.php

$column_types = array_column( $columns_from_table, 'Type', 'Field');
Run Code Online (Sandbox Code Playgroud)

接下来我们要从类型中删除括号,这将类似于 varchar(32) 或 decimal(14,6)

foreach( $column_types as $col=>$type )
{
    $len = strpos( $type, '(' );
    if( $len !== false )
    {
        $column_types[ $col ] = substr( $type, 0, $len );
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们有一个关联数组,以列名作为索引,以格式化类型作为值,例如:

Array
(
    [id] => int
    [name] => varchar
    [balance] => decimal
    ...
)
Run Code Online (Sandbox Code Playgroud)

现在,当您从表中进行选择时,您可以迭代结果并将值转换为适当的类型:

foreach( $results as $index=>$row )
{
    foreach( $row as $col=>$value )
    {
        switch( $column_types[$col] )
        {
            case 'decimal':
            case 'numeric':
            case 'float':
            case 'double':

                $row[ $col ] = (float)$value;
                break;

            case 'integer':
            case 'int':
            case 'bigint':
            case 'mediumint':
            case 'tinyint':
            case 'smallint':

                $row[ $col ] = (int)$value;
                break;
        }

    }
    $results[ $index ] = $row;
}
Run Code Online (Sandbox Code Playgroud)

switch 语句可以很容易地修改以适应,并且可以包括日期函数等。例如,在我的情况下,第 3 方将货币值作为小数推入数据库,但是当我获取该数据并需要将其返回为JSON,我需要这些是数字,而不是字符串。

使用 PHP 7、7.2 和 JQuery 2、3 进行测试。