用 PHP 给 APP 做后台就是有点麻烦,因为 APP 的 JAVA 和 OC 都是强类型的。 PHP 是弱类型的,从 MySQL 数据库取出的字段全为 string 类型的,对 PHP 自身来说,没什么问题,但是对 APP 来说是个灾难。 每次取数据都转换很显然工作量很大。 之前是使用 ThinkPHP 来解决这个问题,但是不太优雅,需要修改框架源码,后来采用了更好的解决方案,直接在 MySQL 连接驱动层面解决问题。

首先确保使用 PDO 连接数据库( PHP 官方推荐)。然后 PDO 设置如下即可:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);

对于 MySQL 到 PHP 数据类型的转换关系

MySQL PHP
FLOAT, DOUBLE double(float)
INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT int
DECIMAL, NUMERIC string
BIGINT (在操作系统 int 范围内是 int,超过范围后是 string) int | sring
other.. string

下面是 ThinkPHP 框架内处理部分,思路仅供参考。建议采用上面的 PDO 方案。

建议所有涉及到类型转换的都继承 CommonModel 而不是 Model 。

_after_find($result, $options);
        }
    }

    protected function _after_find(&$result, $options)
    {
        foreach ($result as $field => $value) {
            $this->_parseType($result, $field);
        }
    }
}

转换的核心方法是$this->_parseType($result, $field); 这里对 TP 原本的方法进行了修改,原来的有个 BUG。 然后还赠添了一种类型的检测————"tinyint"。 如果有需要检测的字段,做相应添加即可。

/**
     * 数据类型检测
     * @access protected
     * @param mixed $data 数据
     * @param string $key 字段名
     * @return void
     */
    protected function _parseType(&$data,$key) {
        if(!isset($this->options['bind'][':'.$key]) && isset($this->fields['_type'][$key])){
            $fieldType = strtolower($this->fields['_type'][$key]);
            if(false !== strpos($fieldType,'enum')){
                // 支持ENUM类型优先检测
            }elseif(false !== strpos($fieldType,'tinyint')){//新添加的字段类型
                $data[$key]   =  intval($data[$key]);
            }elseif(false === strpos($fieldType,'bigint') && 0 === strpos($fieldType,'int')) {
                $data[$key]   =  intval($data[$key]);
            }elseif(false !== strpos($fieldType,'float') || false !== strpos($fieldType,'double')){
                $data[$key]   =  floatval($data[$key]);
            }elseif(false !== strpos($fieldType,'bool')){
                $data[$key]   =  (bool)$data[$key];
            }
        }
    }

这个只支持 select()find() 这俩种方法,其他的比如 getField() 等取单个字段的方法不支持,不过单个字段再转换类型的工作量要小很多。

注意!使用原生的 execute()query() 是不支持的,我看了下源码,框架也没对这种原生的方法做更多中间操作。

本作品由 程小白 创作,采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可,可自由转载、引用但需署名作者且注明文章出处。
原文地址:https://www.chengxiaobai.cn/php/solve-the-php-from-the-database-to-remove-the-field-full-of-string-type.html