如何将JSON加载到Silverstripe Dataobject的字段中

时间:2019-03-04 02:21:10

标签: php silverstripe silverstripe-4

最近的Silverstripe版本升级到4.3.1似乎破坏了一些功能,该功能将数据对象作为JSON加载到Textfield中。

对象看起来像这样:

class Foo extends DataObject 

  private static $db = [
    'Name' => 'Varchar',
    'Description' => 'Text',
    'Models' => 'Text',
  ];

然后有一个函数,可以使用从表单请求生成的JSON加载对象:

$data = json_decode($request->getBody(), true);
$foo = new Foo();
$foo->update($data);

这是JSON $data的示例:

"Name":"Test",
"Description":"Wangle fangle blurble wurgle.",
"Models":{
   "fish":{"trout":10,"salmon":15,"sturgeon":20},
   "vegetable":{"carrot":1,"cabbage":2,"leek":3},
   "sauce":{"chipotle":6,"tomato":4,"soy":2}
 }

直到最近,“模型”结构都将以文本形式保存到“模型”字段中:

 "fish":{"trout":10,"salmon":15,"sturgeon":20},
 "vegetable":{"carrot":1,"cabbage":2,"leek":3},
 "sauce":{"chipotle":6,"tomato":4,"soy":2}

但是现在我们收到以下错误:

DataObject::setField: Models only accepts scalars at /var/www/example/vendor/silverstripe/framework/src/ORM/DataObject.php:2648

DataObject.php中的第2640行说:

If this is a proper database field, we shouldn't be getting non-DBField objects

最近是否有一个安全修复程序阻止了将JSON对象加载到字段中的尝试?

任何人都可以帮助将Models JSON保存到文本字段中吗?

1 个答案:

答案 0 :(得分:3)

@wmk在此处起作用,这是防止安全漏洞的预期行为(请参阅SS-2018-021)。 4.3.1中的更改​​是为了防止您在将数据库字段指定为标量类型时无意中允许用户将非标量值插入数据模型。

在您的情况下,您尝试将一个数组写入文本字段,该文本字段已被silverstripe / framework正确阻止。

这里最简单的解决方法是将数据存储中要存储为JSON文本Blob的部分重新编码,例如:

$data = json_decode($request->getBody(), true);
$data['Models'] = json_encode($data['Models']); // re-encode as JSON before saving
$foo = new Foo();
$foo->update($data);

这将确保您仍将JSON作为文本写入到“文本”字段中。

还有@wmk,另一个可行的选择是编写自己的DBField,它接受非标量值并负责将其安全地写入数据库。如果您正在编写处理GIS or spatial data的DBField,这将很有用。在您的特定示例中,我认为您可以放心确保仍将其编码为字符串作为示例。