Contributed by
Samuel Roze
in #24375.
当操作高度相似的对象,或共享很多属性时,使用接口和抽象类就很常见了。对于继承了其他抽象类的类,有一个问题是 Serializer组件 无从得知如何正确地 serialize/deserialize 它们。
在 Symfony 4.1 中,我们改进了 Serializer 组件,通过使用一个 "discriminator class mapping(鉴别器类映射) " 来对此功能进行支持。思考一个程序,它定义了一个抽象类 CodeRepository
,该类被 GitHubCodeRepository
和
BitBucketCodeRepository
所继承。本例展示了在框架外单纯使用Serializer组件时,如何序列化和反序列化这些对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | // ...
$discriminator = new ClassDiscriminatorResolver();
// $type is the property used to differentiate between classes
// $type 属性用于区分这些类
$discriminator->addClassMapping(
CodeRepository::class,
new ClassDiscriminatorMapping('type', [
'github' => GitHubCodeRepository::class,
'bitbucket' => BitBucketCodeRepository::class,
])
);
// pass the discriminator as the last argument of the normalizer
// 把 discriminator(鉴别器) 作为 normalizer 的最后一个参数传入
$serializer = new Serializer(
array(new ObjectNormalizer(null, null, null, null, $discriminator)),
array('json' => new JsonEncoder())
);
// when serializing, the discriminator knows that the value of the "type"
// property for GitHubCodeRepository classes must be set to {"type": "github"}
// 序列化时,discriminator 知道 "type" 的值
// GitHubCodeRepository 类中的属性必须被设置为 {"type": "github"}
$serialized = $serializer->serialize(new GitHubCodeRepository());
// when deserializing into the abstract CodeRepository class, the discriminator
// uses the "type" value to know that $repository must be an instance of GitHubCodeRepository
// 对 CodeRepository 抽象类反序列化时,discriminator
// 使用 "type" 值来获知 repository 必须是 GitHubCodeRepository 的一个实例
$repository = $serializer->unserialize($serialized, CodeRepository::class, 'json'); |
在 Symfony 程序中使用此功能时,你可以直接把上述所有在 YAML 或 XML 文件中进行配置 ,甚至使用PHP annotations:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | namespace App\Repository;
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
/**
* @DiscriminatorMap(typeProperty="type", mapping={
* "github"="App\Repository\GitHubCodeRepository",
* "bitbucket"="App\Repository\BitBucketCodeRepository"
* })
*/
interface CodeRepository
{
// ...
} |
关于此项新功能的更多内容请参考 Serializer组件文档中的 Serializing Interfaces and Abstract Classes 小节。