Symfony 序列化期间如何动态添加 DTO 属性?
2024-03-04 00:36:55
## Symfony 序列化期间动态添加 DTO 属性
引言
在使用 Symfony 序列化器对数据传输对象 (DTO) 进行序列化时,有时我们需要根据外部条件动态添加属性。传统的解决方案涉及创建自定义类,这可能会导致维护问题。本文将探讨一种更通用的方法,无需创建自定义类即可动态添加属性。
问题
我们的目标是根据查询参数 $portal
的值,向对象添加属性 portal
。传统的解决方案需要为每个可能的 portal
值创建自定义类,如下所示:
class FooBar {
# 各种属性
}
class FooBarContainsCustomPropA extends FooBar {
public string $portal = 'Portal A';
}
class FooBarContainsCustomPropB extends FooBar {
public string $portal = 'Portal B';
}
随着可能数百个用户定义的入口,这种解决方案变得难以维护。
解决方案
为了避免创建自定义类,我们可以使用 PropertyAccessor
从对象中获取属性。如果属性不存在,我们可以创建该属性并设置其值:
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
$propertyAccessor = PropertyAccess::createPropertyAccessor();
if (!$propertyAccessor->isPropertyInitialized($my_object, 'portal')) {
$propertyAccessor->setValue($my_object, 'portal', $portal);
}
步骤:
- 使用
PropertyAccess
创建一个PropertyAccessor
对象。 - 检查属性
portal
是否已初始化。 - 如果属性未初始化,则创建该属性并设置其值。
示例
让我们看一个示例,展示如何使用此方法根据 $portal
值动态添加 portal
属性:
$content = $response->getContent();
$my_object = $this->serializer->deserialize(
$response->getContent(),
FooBar::class."[]",
'json',
[ UnwrappingDenormalizer::UNWRAP_PATH => '[data][someObjectList]' ]
);
$propertyAccessor = PropertyAccess::createPropertyAccessor();
if (!$propertyAccessor->isPropertyInitialized($my_object, 'portal')) {
$propertyAccessor->setValue($my_object, 'portal', $portal);
}
输出
{
"some": "prop",
"another": "property",
"portal": "Portal B"
}
结论
本文介绍了一种使用 PropertyAccessor
在 Symfony 序列化期间动态添加 DTO 属性的方法,无需创建自定义类。这种方法更加通用且易于维护,因为它允许我们根据任何外部条件添加属性。
常见问题解答
-
PropertyAccessor
可以用于哪些类型的对象?
PropertyAccessor
可以用于任何实现了ArrayAccess
或PropertyAccessInterface
接口的对象。 -
为什么使用
isPropertyInitialized
方法?
isPropertyInitialized
方法检查属性是否已设置或读取,从而避免了不必要的属性创建。 -
除了
portal
属性,还可以使用此方法添加其他属性吗?
是的,此方法可以用于添加任何所需的属性。 -
此方法是否适用于嵌套对象?
是的,PropertyAccessor
可以处理嵌套对象,允许您访问和设置嵌套属性。 -
如果属性已存在,此方法会发生什么?
如果属性已存在,此方法将覆盖其值。