如何在Laravel 8中转换PostgreSQL存储的Ruby Hash格式数据
实现方案
你存储的是Ruby生态下ActiveSupport序列化生成的YAML格式数据,要转换为Laravel可用的格式可按以下步骤操作:
1. 安装依赖
使用Symfony的YAML组件处理带自定义标签的YAML内容,Laravel项目默认已包含该组件,未安装的话执行:
composer require symfony/yaml
2. 解析YAML并转换为PHP数组
你存储的YAML中带有!ruby/hash:ActiveSupport::HashWithIndifferentAccess这类Ruby自定义类型标签,需要递归处理转为普通PHP关联数组:
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Tag\TaggedValue; // 从PostgreSQL中读取原始YAML字符串 $rawYaml = '你的数据库查询得到的YAML内容'; // 解析带自定义标签的YAML $parsedRaw = Yaml::parse($rawYaml, Yaml::PARSE_CUSTOM_TAGS); // 递归处理Ruby自定义哈希标签 function transformRubyHash($data) { // 匹配Ruby哈希标签,转换为普通数组 if ($data instanceof TaggedValue && str_starts_with($data->getTag(), '!ruby/hash:')) { return transformRubyHash($data->getValue()); } // 递归处理数组内所有元素 if (is_array($data)) { return array_map(fn($item) => transformRubyHash($item), $data); } return $data; } $phpArray = transformRubyHash($parsedRaw);
按你给出的示例数据,转换后得到的数组结构如下:
[ 'accepted' => [ 'number_of_order' => [ 'condition' => 'between_number', 'value' => '0&5' ] ], 'removed' => [] ]
3. 调整为目标格式
得到普通PHP数组后,可按业务需求自由修改、补充字段得到你需要的目标结构:
// 补充accepted下的字段 $phpArray['accepted']['last_order_total'] = [ 'condition' => 'between_number', 'value' => '1000&2000' ]; $phpArray['accepted']['last_order_date'] = [ 'condition' => 'before', 'value' => '2021-10-01T00:00:00.000Z' ]; $phpArray['accepted']['number_of_order']['value'] = '10&20'; // 补充removed下的字段 $phpArray['removed']['last_order_date'] = [ 'condition' => 'after', 'value' => '2021-10-14T00:00:00.000Z' ]; $phpArray['removed']['last_order_total'] = [ 'condition' => 'between_number', 'value' => '1200&1500' ];
4. 输出指定格式
如果要输出你示例中=>格式的字符串,直接调用var_export即可:
echo var_export($phpArray, true);
需要JSON格式的话调用json_encode($phpArray)即可。
5. Laravel模型自动转换(可选)
如果需要在Eloquent模型中自动完成解析转换,可以定义访问器和修改器:
// 访问器:读取字段时自动转为PHP数组 public function getYourFieldNameAttribute($value) { $parsed = Yaml::parse($value, Yaml::PARSE_CUSTOM_TAGS); return transformRubyHash($parsed); } // 修改器:存储时自动序列化 public function setYourFieldNameAttribute($value) { // 若不需要兼容原有Ruby系统,建议直接转为JSON存入PostgreSQL的jsonb字段,性能更高 $this->attributes['your_field_name'] = Yaml::dump($value); }
优化建议
如果后续不再有Ruby程序读写该字段,建议将PostgreSQL中存储该内容的字段类型改为jsonb,批量转换所有历史数据后无需每次读取都解析YAML,还可直接使用PostgreSQL的JSON查询语法操作数据。
内容的提问来源于stack exchange,提问作者HG Webs
相关产品推荐
相关产品推荐

