【发布时间】:2017-09-06 23:52:37
【问题描述】:
我正在将 Zend Framework 3 应用程序的 Zend\Db 驱动 DBAL 迁移到 Doctrine。一切正常,但现在我在导出数据时遇到了问题。
在迁移之前,它的工作方式如下:
有一个或多或少复杂的数据结构。 Mapper 执行了一些数据库请求,并根据这些数据构建了一个嵌套的DataObject。因此,导出的起点是一个对象,其中填充了所有数据并具有子对象以及它们的所有数据。所以我简单地将其转换为JSON:
public function exportToJson(AbstractDataObject $dataObject)
{
return json_encode($dataObject, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
public function exportToXml(AbstractDataObject $dataObject)
{
$dataObjectVars = json_decode(json_encode($dataObject->jsonSerialize()), true);
$xml = new \SimpleXMLElement('<' . self::XML_DEFAULT_ROOT_ELEMENT . ' />');
$this->arrayToXml($dataObjectVars, $xml);
$domxml = new \DOMDocument('1.0');
$domxml->preserveWhiteSpace = false;
$domxml->formatOutput = true;
$domxml->loadXML($xml->asXML());
$xmlString = $domxml->saveXML();
return $xmlString;
}
protected function arrayToXml($array, &$xml)
{
foreach ($array as $key => $value) {
if(is_array($value)){
if(is_int($key)){
$key = self::XML_DEFAULT_ELEMENT_NAME;
}
$label = $xml->addChild($key);
$this->arrayToXml($value, $label);
}
else {
$xml->addChild($key, $value);
}
}
}
所有DataObjects 都扩展了AbstractDataObject,并提供了一种方法,可以轻松导出到JSON:
class AbstractDataObject implements \JsonSerializable
{
public function jsonSerialize()
{
$reflection = new \ReflectionClass($this);
$properties = $reflection->getProperties();
$members = [];
foreach ($properties as $property) {
$property->setAccessible(true);
$members[$property->getName()] = $property->getValue($this);
}
$keys = array_keys($members);
$values = array_values($members);
$keysUnderscored = preg_replace_callback('/([A-Z])/', function($matches) {
return '_' . strtolower($matches[1]);
}, $keys);
$varsUnderscored = array_combine($keysUnderscored, $values);
return $varsUnderscored;
}
}
现在要导出的对象是一个实体,它通常不会加载所有数据。这意味着,上述方法不再有效。
是否有/将嵌套实体(指具有子实体的实体)转换为结构化数据格式(array/JSON/XML)的正确方法?强>
【问题讨论】:
-
您可以通过使用查询并在 select 子句中指定所有相关实体来加载实体。这基本上会覆盖延迟加载。或者您可以调整序列化程序以调用 getPropertyName() 而不是直接访问属性。最后,你可以看看 Symfony 序列化器组件,它可能是做这些事情的“官方”方式。现在我想,如果你真的不需要一个对象,那么 $query->getArrayResult() 可能就是你所需要的。
-
@Cerad 非常感谢您的评论!因此,您建议树方式:
1.具有所有依赖项的查询。 ——这会很大,我想避免这种情况。2.要“调整序列化程序以调用 getPropertyName() 而不是直接访问属性”。 什么意思?3.Symfony 序列化组件。我会看看。感谢您的建议!4.$query->getArrayResult()-- 这将是一个非常优雅的解决方案,但它不适用于嵌套结构。 -
考虑使用缺少数据的实体的简单示例来更新您的问题。我认为您在延迟加载时遇到了问题,但我不确定。
-
跟进@Cerad 评论,您可以创建一个custom hydration mode,它将返回一个包含所有嵌套对象的数组
标签: php arrays json doctrine-orm data-conversion