ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Doctrine JSON ODM常见问题清单:8个高频踩坑场景(JSONB、命名空间迁移、自定义Normalizer)速查

Doctrine JSON ODM常见问题清单:8个高频踩坑场景(JSONB、命名空间迁移、自定义Normalizer)速查 Doctrine JSON ODM常见问题清单8个高频踩坑场景JSONB、命名空间迁移、自定义Normalizer速查【免费下载链接】doctrine-json-odmAn object document mapper for Doctrine ORM using JSON types of modern RDBMS.项目地址: https://gitcode.com/gh_mirrors/do/doctrine-json-odmDoctrine JSON ODM 是一个基于现代 RDBMSPostgreSQL / MySQLJSON 与 JSONB 列类型的对象文档映射器Object-Document Mapper它能把任意 PHP 对象图当作 JSON 文档存进关系数据库读回时还原为原始对象并支持用数据库原生 JSON 函数查询这些无 schema数据。本文速查Doctrine JSON ODM 的 8 个高频踩坑场景——JSONB 选型、Serializer 缺失报错、命名空间迁移、type_map 类型别名、自定义 Normalizer 等每个场景都给出症状 → 原因 → 解法三步速查。项目速览先建立全局认知 在排查问题前先了解这张地图80% 的问题都能快速定位到对应模块能力关键文件路径JSON 列类型MySQL / 通用src/Type/JsonDocumentType.phpJSONB 列类型需 DBAL 4.3.0src/Type/JsonbDocumentType.php序列化核心逻辑src/Type/JsonDocumentTypeTrait.php、src/SerializerTrait.php类型映射#type 别名机制src/TypeMapper.php、src/TypeMapperInterface.phpSymfony Bundle 服务注册src/Bundle/Resources/config/services.phpBundle 配置项type_mapsrc/Bundle/DependencyInjection/Configuration.php核心机制一句话写入时PHP 对象 → Symfony Serializer 序列化为带#type字段记录类名的 JSON读取时根据#type反序列化回原对象。后续几乎所有坑都围绕这条主线。场景 1JSONB 选型踩坑——json_document 与 jsonb_document 分不清 ⚠️症状想在 PostgreSQL 里存 JSONB 但字段实际是 JSON或升级到 DBAL 4.3 后不知该用哪种写法。原因项目提供两种列类型能力与适用版本不同json_document基于 DBAL 通用JsonType兼容 PostgreSQL 9.4 与 MySQL 5.7jsonb_document基于 DBAL 原生JsonbType要求 DBAL ≥ 4.3.0见src/Type/JsonbDocumentType.php的注释。速查解法DBAL ≥ 4.3.0 → 直接#[Column(type: jsonb_document)]老版本 DBAL → 用#[Column(type: json_document, options: [jsonb true])]。 选型口诀新环境用jsonb_document老环境用jsonb选项两者都别混用到同一字段。场景 2报错An instance of SerializerInterface must be available 症状非 Symfony 项目中首次读写json_document字段时抛RuntimeException。原因JsonDocumentTypeTraitsrc/Type/JsonDocumentTypeTrait.php内部持有 Serializer未调用setSerializer()时访问即抛异常。Symfony / API Platform 环境由 Bundle 自动装配无需处理裸用 Doctrine 时必须手动注册类型并注入 Serializer。速查解法启动时按顺序做三件事——Type::addType(json_document, JsonDocumentType::class); Type::getType(json_document)-setSerializer($serializer); // DBAL 4.3.0 再注册 jsonb_document$serializer需包含ArrayDenormalizer、ObjectNormalizer、DateTimeNormalizer等完整示例见 README 的 Install 章节。 附带小坑数据库里空字符串会被读成null见JsonDocumentTypeTrait::convertToPHPValue若业务区分空与无值序列化输出前自行兜底。场景 3嵌套属性修改了UPDATE 语句却不生成 ✍️症状改了$foo-misc里的嵌套对象属性flush()后数据库纹丝不动。原因Doctrine ORM 按引用比较新旧对象以优化 UPDATE 查询——嵌套属性是原地修改引用未变变更检测器视之为无变化。这是官方文档明确列出的限制README 的Limitations when updating nested properties。速查解法赋值前先clone制造新引用让 Doctrine 察觉变更$foo-misc clone $foo-misc; $foo-misc[0]-title 新标题; $entityManager-flush(); // 现在会生成 UPDATE记忆点JSON 文档列的整体替换没问题局部原地改才踩坑。场景 4类命名空间迁移后历史数据读不出来 症状项目从AppBundle迁到App后旧记录反序列化报Class not found或类型错误。原因默认情况下#type字段存的是完整类名FQCN改名后数据库里的旧 FQCN 已指向不存在的类。速查解法MySQL用 JSON 函数批量改写存量数据README FAQ 提供官方写法UPDATE baz SET misc JSON_REPLACE(misc, $.#type, App\\Entity\\Bar) WHERE AppBundle\\Entity\\Bar JSON_EXTRACT(misc, $.#type);️ 预防优于救火新项目一开始就配置type_map类型别名见场景 5以后移动/重命名文档类只改配置不迁数据。场景 5一行 type_map 配置同时解决存储膨胀与命名空间变更风险 ️收益README 明确列出的两点文档类移动/重命名时只改配置不迁库旧数据存全类名仍可正常反序列化百万级记录时短别名比 FQCN更省存储空间。速查配置config/packages/doctrine_json_odm.yamldunglas_doctrine_json_odm: type_map: foo: App\Something\Foo bar: App\SomethingElse\Bar配置后Foo对象序列化为{ #type: foo, ... }。注意两点type_map的 value 必须是真实存在的完整类名配置校验会拦截见src/Bundle/DependencyInjection/Configuration.php未配置时type_mapper服务会被移除见src/Bundle/DependencyInjection/DunglasDoctrineJsonOdmExtension.php属正常行为。场景 6更动态的类型映射——自定义 TypeMapper 实现指南 适用别名不是静态映射而需要查库、加前缀、做兼容逻辑等动态场景。速查解法实现接口getTypeByClass()类名 → 类型字符串与getClassByType()类型字符串 → 类名参考内置实现src/TypeMapper.php与接口src/TypeMapperInterface.phpSymfony 环境在services.yaml中覆盖服务定义dunglas_doctrine_json_odm.type_mapper为你的实现即可无需改代码非 Symfony 环境把实现实例作为第三个构造参数传入Dunglas\DoctrineJsonOdm\Serializer。序列化侧的读写逻辑在src/SerializerTrait.php写入时给对象注入#type标量再包一层#scalar读取时先按#type还原目标类这正是命名空间迁移问题的根源也说明自定义 mapper 只影响字符串 ↔ 类的翻译层风险可控。场景 7自定义 Normalizer 不生效关键在于注入顺序 症状往序列化器里加了自定义 Normalizer结果没走你的逻辑或行为错乱。原因Bundle 通过服务dunglas_doctrine_json_odm.serializer注册于src/Bundle/Resources/config/services.php持有 Normalizer 链链是有序数组——Symfony Serializer 按顺序找到第一个能处理的类型即停止顺序错就会被先来的 Normalizer 截胡。速查解法在services.yaml中覆盖dunglas_doctrine_json_odm.serializer定义重写 normalizers 参数数组。要点你的自定义 Normalizer 放在目标类型之前如放在datetime、object之前保留原有 Normalizer 的相对顺序backed_enum → uid → datetime → array → object测试用例参考tests/Fixtures/TestBundle/DependencyInjection/InjectCustomNormalizerPass.php的注入思路。这是官方 FAQREADME How can I add additional normalizers?给出的标准做法无需修改 Bundle 源码。场景 8JSON 输出格式不符合预期修改序列化/反序列化上下文 ⚙️症状JSON 里斜杠被转义成\/、日期格式不对等怀疑序列化行为不可控。原因列类型默认使用空上下文JSON 编码选项如JSON_UNESCAPED_SLASHES未开启。速查解法Symfony 环境在 Kernel 的boot()中一次性设置README FAQ 有完整示例$type Type::getType(json_document); $type-setSerializationContext([JsonEncode::OPTIONS JSON_UNESCAPED_SLASHES]); $type-setDeserializationContext([/* 反序列化选项 */]);setSerializationContext/setDeserializationContext定义在src/Type/JsonDocumentTypeTrait.phpjson_document与jsonb_document两个类型都可用。附录版本兼容与排查速查表 ✅检查项要求PostgreSQL≥ 9.4MySQL≥ 5.7JSON 列需 5.7.8Doctrine ORM / DBALORM ≥ 2.6DBAL ≥ 2.6jsonb_document类型DBAL ≥ 4.3.0自定义类型映射服务dunglas_doctrine_json_odm.type_mapper序列化器服务dunglas_doctrine_json_odm.serializer排查顺序建议先确认数据库与 DBAL 版本场景 1/2→ 再看#type与命名空间场景 4/5→ 最后才怀疑 Normalizer 与上下文场景 7/8。掌握这 8 个场景Doctrine JSON ODM 日常开发中遇到的绝大多数问题都能三分钟定位。【免费下载链接】doctrine-json-odmAn object document mapper for Doctrine ORM using JSON types of modern RDBMS.项目地址: https://gitcode.com/gh_mirrors/do/doctrine-json-odm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表