webit / doctrine-jms-json
使用 JMS Serializer 转换复杂对象
Requires
- php: >=7.2
- ext-json: *
- doctrine/collections: ^1.5.0|^2.0.0
- doctrine/dbal: ^2.10.0|^3.0.0
- jms/serializer: ^2.0.0|^3.0.0
Requires (Dev)
- phpspec/prophecy: ^1.17
- phpunit/phpunit: ^8.0.0
README
使用 Doctrine 通过 JMS Serializer 持久化值对象。DBAL 类型支持 JMS Serializer 可以处理的所有内容(标量、数组、Doctrine 集合、DateTime 等)。
安装
将 "webit/doctrine-jms-json": "^2.0.0" 添加到你的 composer.json 的 require 部分
{ "require": { "webit/doctrine-jms-json": "^3.0.0" } }
用法
配置注册新的 Doctrine DBAL 类型并配置序列化器
# boostrap.php use Doctrine\DBAL\Types\Type; use Webit\DoctrineJmsJson\DBAL\JmsJsonType; use JMS\Serializer\SerializerBuilder; use Webit\DoctrineJmsJson\Serializer\Type\DefaultSerializerTypeResolver; Type::addType('jms_json', 'Webit\DoctrineJmsJson\DBAL\JmsJsonType'); $serializer = SerializerBuilder::create()->build(); // initialize JmsJsonType JmsJsonType::initialize($serializer, new DefaultSerializerTypeResolver());
现在你可以在 Doctrine 字段映射中使用 "jms_json" 作为类型。
请参阅 JMS Serializer 的完整配置 这里 请参阅 Doctrine 映射的完整文档 这里 请参阅 Doctrine 自定义类型文档 这里
示例
"jms_json" DBAL 类型可以非常方便地存储 值对象 或结构可能变化的对象。
以网页上的一个 滑块 为例。让类 BannerSet 包含 Slider 配置。
interface Slider { } class BannerSet { private $id; /** Slider */ private $slider; /** * @return Slider */ public function slider() { return $this->slider; } /** * @param Slider $slider */ public function changeSlider(Slider $slider) { $this->slider = $slider; } }
JavaScript 滑块配置有很多种,我们事先不知道其结构。让我们引入两种实现
use JMS\Serializer\Annotation as JMS;
class Slider1 implements Slider
{
/**
* @JMS\Type("string")
*/
private $theme;
/**
* @JMS\Type("double")
*/
private $slideTime;
// ...
}
class Slider2 implements Slider
{
/**
* @JMS\Type("array<string>")
*/
private $effects;
/**
* @JMS\Type("boolean")
*/
private $stopOnHover;
/**
* @JMS\Type("integer")
*/
private $pauseTime;
// ...
}
要使用 Doctrine ORM 将 BannerSet 持久化到数据库,我们需要提供映射。使用标准的关系方法,我们需要映射 BannerSet 和每个 Slider(可能使用 [单表继承])。这意味着,我们将有两个数据库表 "banner_set" 和 "slider",它们之间存在一对一的关系 - 对于存储滑块配置来说相当复杂。而且,这种方法需要将 Slider 实例作为实体存储(我们必须引入 ID 以存储在表中),这破坏了我们的模型。
滑块配置只是我们需要存储的对象,我们不需要查询它。因此,将其存储在 "banner_set" 表的一个列中的 JSON 格式中会更简单。
BannerSet Doctrine 映射文件将看起来像这样
entity: class: BannerSet id: id: type: int fields: slider: type: jms_json
就是这样!
显然,我们需要为 Slider1 和 Slider2 提供序列化器的映射(可以通过不同的方式完成,例如通过注释 - 查看更多详细信息,请参阅 JMSSerializer 文档)。
Symfony 2/3 集成
请参阅 WebitDoctrineJsonBundle Symfony 2/3 集成。
测试
composer install
./vendor/bin/phpunit
变更日志
版本 2.0.0
引入了对原生 JSON 类型数据库字段的支持。内部数据以有效的 JSON 格式存储('{"_jms_type": "Deserialisation Type", "data": "DATA TO BE DESERIALISED"}')。这破坏了与版本 1.x 的向后兼容性。版本 1.x 不能升级到 2.x 而不进行手动转换已保存的数据。
版本 2.1.0
在转换为PHP值(从数据库读取)时,与版本 1.x 兼容。请注意,从版本 1.x 格式读取的数据将在实体的刷新过程中自动转换为新的格式。
版本 3.0.0
支持更高的JMS Serializer版本(2.x、3.x)。此版本需要PHP >= 7.2。