Doctrine向数据库文本字段存布尔值如何实现true存't'、false存'f'
运行环境
- doctrine/doctrine-bundle:2.5.6
- PostgreSQL:12.5-1.pgdg100+1
- 技术栈:PHP 8、Symfony
问题表现
向数据库文本类型字段存储布尔值时,布尔值为false时字段存入空字符串,布尔值为true时字段存入'1',不符合预期。
预期效果:布尔值为
true时存入't',布尔值为false时存入'f'
当前使用的代码如下:
$conn->executeQuery( 'INSERT INTO example_table (example_true, example_false) VALUES(:example_true, :example_false)', [ "example_true" => true, "example_false" => false ]);
问题根因
Doctrine DBAL 适配 PostgreSQL 原生布尔类型的默认转换规则为:true 转为字符串 '1'、false 转为空字符串,该规则是为了匹配 PostgreSQL 原生 bool 类型字段的写入逻辑,当前使用文本类型字段存储布尔值,默认转换规则和预期的 t/f 存储格式不匹配,因此出现异常写入结果。
实现方案
根据业务场景二选一即可:
方案1:单次调用手动转换(无额外配置,适合少量使用场景)
直接在传参时做值映射,不需要修改任何框架配置,修改后代码:
$conn->executeQuery( 'INSERT INTO example_table (example_true, example_false) VALUES(:example_true, :example_false)', [ "example_true" => true ? 't' : 'f', "example_false" => false ? 't' : 'f' ] );
方案2:自定义Doctrine类型(全局生效,适合多处复用场景)
如果项目中有大量同类写入需求,通过自定义DBAL类型一劳永逸解决,不需要每次手动转换:
- 新建自定义类型类,重写布尔值的库表转换逻辑:
<?php // src/Doctrine/Type/TextBooleanType.php namespace App\Doctrine\Type; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\BooleanType; class TextBooleanType extends BooleanType { /** * PHP值转数据库存储值 */ public function convertToDatabaseValue($value, AbstractPlatform $platform) { if ($value === null) { return null; } return $value ? 't' : 'f'; } /** * 数据库存储值转PHP布尔值 */ public function convertToPHPValue($value, AbstractPlatform $platform) { if ($value === null || $value === '') { return null; } return in_array(strtolower($value), ['t', '1', 'true'], true); } public function getName() { return 'text_boolean'; } }
- 在Symfony的Doctrine配置文件
config/packages/doctrine.yaml中注册该类型:
doctrine: dbal: types: text_boolean: App\Doctrine\Type\TextBooleanType
- 使用时两种方式可选:
- 方式A:写入时指定参数类型,不需要全局修改默认规则
$conn->executeQuery( 'INSERT INTO example_table (example_true, example_false) VALUES(:example_true, :example_false)', [ "example_true" => true, "example_false" => false ], [ "example_true" => 'text_boolean', "example_false" => 'text_boolean' ] );
- 方式B:如果要让所有布尔参数默认按
t/f格式写入文本字段,直接在配置中添加映射规则覆盖默认布尔类型转换即可:
doctrine: dbal: types: text_boolean: App\Doctrine\Type\TextBooleanType mapping_types: bool: text_boolean
配置后不需要修改原有业务代码,所有布尔值写入都会自动转为t/f格式。
内容的提问来源于stack exchange,提问作者Anton_V
相关产品推荐
相关产品推荐

