zend-db结合zend-expressive时如何实现查询结果自动类型转换?
解决zend-db查询返回JSON时数值字段转字符串的问题
我之前在使用zend-db搭配zend-expressive开发时也碰到过一模一样的问题——MySQL里的INTEGER类型字段,查询后返回的JSON里变成了字符串类型。其实有几种靠谱的方法可以实现自动类型转换,根据你的场景选就行:
方法一:全局配置PDO适配器,开启原生类型返回
这是最省心的全局解决方案,因为PDO默认会把所有数据库返回的数值类型转成字符串,我们只需要在初始化数据库适配器时关闭这个行为:
// 示例:在配置文件中初始化dbAdapter时添加driver_options $dbConfig = [ 'driver' => 'Pdo_Mysql', 'database' => '你的数据库名', 'username' => '用户名', 'password' => '密码', 'driver_options' => [ PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_EMULATE_PREPARES => false, ], ]; $dbAdapter = new Zend\Db\Adapter\Adapter($dbConfig);
注意事项:
ATTR_EMULATE_PREPARES设为false是必须的,因为如果开启模拟预处理,PDO还是会把数值转成字符串。- 关闭模拟预处理后,某些MySQL的语法特性(比如
LIMIT使用占位符)可能需要调整写法,建议测试一下现有代码的兼容性。
方法二:使用HydratingResultSet配合Hydrator做字段级类型转换
如果只需要针对个别字段做类型转换,不想全局修改配置,可以用HydratingResultSet搭配Hydrator来精准控制:
use Zend\Db\ResultSet\HydratingResultSet; use Zend\Hydrator\ArraySerializableHydrator; use Zend\Db\Sql\Select; use Zend\Db\Sql\Sql; public function handle(ServerRequestInterface $request) : ResponseInterface { $select = new Select(); $select->from('person'); $select->columns([ 'id', 'name', ]); $sql = new Sql($this->dbAdapter); $statement = $sql->prepareStatementForSqlObject($select); $result = $statement->execute(); // 初始化Hydrator并添加id字段的类型转换规则 $hydrator = new ArraySerializableHydrator(); $hydrator->addFilter('id', function($value) { return (int)$value; }, \Zend\Hydrator\HydratorInterface::CONDITION_AND); $resultSet = new HydratingResultSet($hydrator); $resultSet->initialize($result); return new JsonResponse($resultSet->toArray()); }
这种方法的好处是可以针对不同字段设置不同的转换规则(比如把某些字段转成float),灵活性很高。
方法三:自定义ResultSet类批量处理类型转换
如果你的项目里有多个表需要处理数值类型转换,可以自定义一个ResultSet类,重写toArray方法来统一处理:
use Zend\Db\ResultSet\ResultSet; class TypedResultSet extends ResultSet { public function toArray() { $data = parent::toArray(); foreach ($data as &$row) { // 处理id字段转int if (isset($row['id'])) { $row['id'] = (int)$row['id']; } // 可以添加更多字段的转换,比如age、score等 if (isset($row['age'])) { $row['age'] = (int)$row['age']; } } return $data; } }
然后在处理器里替换原有的ResultSet:
$resultSet = new TypedResultSet(); $resultSet->initialize($result); return new JsonResponse($resultSet->toArray());
这种方式适合需要统一处理多个字段或多个表的场景,后续维护也方便。
内容的提问来源于stack exchange,提问作者altralaser
相关产品推荐
相关产品推荐

