thinkphp6之数据库更新json字段

在thinkphp6的教程中,JSON数据更新的例子是这样的

	//单个JSON数据更新
 	$data['info->nickname'] = 'ThinkPHP';
	Db::name('user')
	->json(['info'])
    ->where('id',1)
	->update($data);

假设json的结构是这样的多层嵌套

 	{"user": {"bmId": 1245554, "name": "张三", "isUsing": true}, "admin": [], "search_scope": []}

如果写成以下方式,是错误的

	//这个例子是错误的
 	$data['u_authority->user->bmId'] = 1245554;
	Db::name('sys_authority')
	->json(['info'])
    ->where('id',1)
	->update($data);

应该以点来分隔路径,而且只能一次更新一个值

	//正确的例子?
	$path='user->name';
	$val='李四';
 	$data['u_authority->'.$path] =$val;
    Db::name('sys_authority')
    ->json(['u_authority'])
    ->where('id', $id)
    ->update($data);

如果你认为这就没问题了,那就错了,当值为数字的时候,他会转换成字符串存入

	//数字时会转变成字符串
	$path='user->bmId';
	$val=123456;
 	$data['u_authority->'.$path] =$val;
    Db::name('sys_authority')
    ->json(['u_authority'])
    ->where('id', $id)
    ->update($data);

解析成的sql语句与实际写入的不一样,不知道是不是bug

	# 在tp日志中查看log显示为:
	UPDATE `sys_authority`  SET `u_authority` = json_set(`u_authority`, '$.user.bmId', 1646226973523)  WHERE  `id` = 8

	# 在mysql更新时的语句就变成了(通过mysqlbinlog方式查看):

	### UPDATE `login_authority`.`sys_authority`
	### WHERE
	###   @1=8
	###   @2=9
	###   @3=4
	###   @4='{"user": {"bmId": 1245554, "name": "张三", "isUsing": true}, "admin": [], "search_scope": []}'
	### SET
	###   @1=8
	###   @2=9
	###   @3=4
	###   @4='{"user": {"bmId": "123456", "name": "张三", "isUsing": true}, "admin": [], "search_scope": []}'

最终只能通过exp方式直接写函数解决

	//$data举例 ['user.bmId'=>[123456,'int'],'user.name'=>'李四','user.isUsing'=>true,'admin'=>[['0101',123,true],'array']]
public function updateSysAuthority($id,$data){
   $jsonSet='json_set(`u_authority`';
   foreach ($data as $key => $value) {
      if(is_array($value)){
         switch($value[1]){           
            case 'int': 
            case 'bool': {
               $temp=$value[0]?"true":"false";
               $jsonSet.=",'$." . $key ."',". $temp;
               break;
            }
            case 'array':{
               $jsonSet.=",'$." . $key ."',JSON_ARRAY(".implode(',',array_map(function($str){
                  if(is_string($str)) return sprintf("'%s'", $str);
                  if(is_bool($str)) return $str?"true":"false";
                  return $str;
               },$value[0])) .")";
               break;
            }
            case 'str': 
            default:{
               $jsonSet.=",'$." . $key ."','".addslashes($value[0]) ."'";
            }
         }
      }else
      $jsonSet.=",'$." . $key ."','".addslashes($value) ."'";
   }
   $jsonSet.=')';
   return Db::name('sys_authority')//->fetchSql()
    ->where('id',$id)
    ->exp('u_authority', $jsonSet)
    ->update();
}
  • 以上方法仅考虑了$data中仅包含3种类型的情况,如果包含多层如array、object时情况会更复杂。

再此向各位大佬寻求能够设定字段类型的方法,以更简单的方式更新多层嵌套字段的某一值。

你可能感兴趣的:(thinkphp6,json,数据库,php,thinkphp)