我目前正在通过在应用程序中使用Laravel从外部应用程序获取数据。
我在控制器文件中创建了一个简单的webhook,例如:
public function webhook(Request $request)
{
$document = new Document();
$document->fill($request->all());
//Insert (or update existing) data in our database.
$document::updateOrCreate(
['booking_reference' => $document->booking_reference],
$document->getAttributes()
);
return response()->json('OK');
}
现在我的问题是,我必须将此数据插入表中。为此,接收到的json对象应与我的表列的名称匹配。我可以在外部应用程序中设置json名称-但是,有时外部应用程序会在json名称中添加子元素。
例如,假设这是我的数据库:
id | booking_reference | shipment_reference
我的JSON有这些:
"booking_reference" : "32000"
"shipment_reference" : "TREXOOO"
然后将数据正确插入到我的数据库中。但是,如上所述,JSON对象有时可能看起来像这样:
"booking_reference_0" : "32000"
"shipment_reference_5" : "TREX000"
在此示例中,由于JSON名称与我的表名称不匹配,因此不会更新我的表。
该怎么办,以便可以动态地将数据插入表中?数据将始终具有表名的前缀,例如booking_reference
或booking_reference_{child}
更新:
使用Erubiel的答案,我可以使这些列动态匹配名称。但是,我有一个基本的belongsTo关系设置,但是Erubiel的解决方案剥离了$ document对象,只添加了 mapped 列。
$document->creator()->associate(auth()->user());
在我的模型中:
public function creator()
{
return $this->belongsTo(User::class, 'user_id', 'id');
}
但是我的JSON响应不包含任何user_id
或creator
信息:
{"booking_reference":"CDK10000","pickup_location":"Afhentingsadresse 100 2650","drop_off_location":"Leveringsadresse 200 1000","comments":"HaHA","shipment_referenec":"SBRY100000"}
如果在foreach循环之前我刚得到$document
:
{"user_id":1,"creator":{"id":1,"name":"Oliver","email":"oliver@example.com","created_at":"2018-08-27 10:58:10","updated_at":"2018-08-27 10:58:10"}}
最终解决方案和解决方案
使用Erubiel的答案,我只是对其进行了一些修改,以将新值存储在现有的JSON对象中:
foreach ($request->all() as $key => $value) {
$newKey = preg_replace("/(_?\d+)+$/", '', $key); //this generates the name of column that you need
$document->$newKey = $value;
}
哪个像咒符一样工作-输出:
{"user_id":1,"booking_reference":"CDK10000","pickup_location":"Afhentingsadresse 100 2650","drop_off_location":"Leveringsadresse 200 1000","comments":"HaHA","shipment_referenec":"SBRY100000","creator":{"id":1,"name":"Oliver","email":"oliver@example.com","created_at":"2018-08-27 10:58:10","updated_at":"2018-08-27 10:58:10"}}
答案 0 :(得分:1)
这应该按照注释中的建议进行预处理。
public function webhook(Request $request)
{
$arrAux = array();
foreach($request->all() as $key => $value){
$newKey = preg_replace("/(_?\d+)+$/","",$key); //this generates the name of column that you need
$arrAux[$newKey] = $value;
}
//Insert (or update existing) data in our database.
Document::updateOrCreate(
['booking_reference' => $arrAux['booking_reference']],
$arrAux
);
return response()->json('OK');
}
答案 1 :(得分:0)
您解决问题的方法似乎类似于体系结构/设计反模式(基于原始json数据插入)。那不是回答你的问题,只是我的意见。
解决您问题的最快方法似乎是一个接受$ jsonKey并将其转换/返回$ dbKey的类。
您当前的代码:
$document->fill($request->all());
新方法:
$input = $this->translator->fromInput($request->all());
$document->fill($input);
示例净化/翻译类:
class Translator {
/**
* @param array $input
* @return array
*/
public function fromInput(array $input): array
{
$translated = [];
foreach ($input as $key => $value) {
switch ($key){
case 'a':
case 'a_1':
$translated['a'] = $value;
break;
case mb_strpos($key, 'b'):
$translated['b'] = $value;
break;
default: $translated[$key] = $value;
}
}
return $translated;
}
}
答案 2 :(得分:0)
添加受保护的$fillable
属性以及要批量分配给模型的可用字段列表:
protected $fillable = ['booking_reference','shipment_reference'];
然后在控制器中捕获不匹配字段错误
try {
$document->update($request->input());
} catch (MassAssignmentException $e) {
$data = $request->input();
foreach ($data as &$field) {
preg_match('~([a-zA-Z]+(_[a-zA-Z]+)+)~', $field, $match);
$field = $match[1];
}
$document->update($data);
}