think-orm icon indicating copy to clipboard operation
think-orm copied to clipboard

设定$jsonType 后出现update()方法更新字段不存在的问题

Open hainuo opened this issue 3 years ago • 4 comments

设定了 JsonJob 类 JsonJob.php

namespace app\common\model;

use think\Model;

class JsonJob extends Model
{

    protected $jsonAssoc = true;
    protected $json = ['data'];
    // 设置JSON字段的类型
    protected $jsonType = [
        'data->vod_id'	=>	'int'
    ];
}

然后更新操作使用

    JsonJob::where('id', $findNewJob['id'])->update([
        'run_time' => $time,
        'from' => $from,
    ]);

这时候会提示

#0 [10500]DbException in [Builder.php line 164]()
数据表字段不存在:[run_time]
                $val = json_encode($val);
            }

            if (false !== strpos($key, '->')) {
                [$key, $name]  = explode('->', $key, 2);
                $item          = $this->parseKey($query, $key);
                $result[$item] = 'json_set(' . $item . ', \'$.' . $name . '\', ' . $this->parseDataBind($query, $key . '->' . $name, $val, $bind) . ')';
            } elseif (false === strpos($key, '.') && !in_array($key, $fields, true)) {
                if ($options['strict']) {
                    throw new Exception('fields not exists:[' . $key . ']');
                }
            } elseif (is_null($val)) {
                $result[$item] = 'NULL';
            } elseif (is_array($val) && !empty($val) && is_string($val[0])) {
                switch (strtoupper($val[0])) {
                    case 'INC':
                        $result[$item] = $item . ' + ' . floatval($val[1]);
                        break;
                    case 'DEC':

数据表字段 使用 $jsonJob->getTableFields()获取到字段为

array:8 [[▼]()
  0 => "id"
  1 => "type"
  2 => "data"
  3 => "deal_status"
  4 => "error_msg"
  5 => "run_time"
  6 => "from"
  7 => "ip"
]

如果JsonJob.php 类 注释掉

    // 设置JSON字段的类型
    protected $jsonType = [
        'data->vod_id'	=>	'int'
    ];

hainuo avatar Mar 13 '22 11:03 hainuo

thinkorm v4.0 希望对你有帮助, 我数据库是MariaDB 这么处理就可以了

//字段 data 
protected function getOptions(): array
    {
        return [
            'type' => [
                // 设置JSON字段的类型
                'data'	=>	'json'
            ],
            'jsonAssoc'    => true,  // 设置JSON数据返回数组
        ];
    }

21307369 avatar Apr 24 '25 12:04 21307369

jsonType不需要了 直接定义到type里面即可

liu21st avatar Apr 25 '25 02:04 liu21st

json->channel->id 写入或者读取的时候还是字符串

{
  "channel":[     
    {"id":"2","weight":"99"},
    {"id":"7","weight":"99"}
  ]
}
    protected function getOptions(): array
    {
        return [
            'type' => [
                // 设置JSON字段的类型
                'json'	=>	'json',
                'json->channel->id'	=>	'int',
            ]
        ];
    }

21307369 avatar Apr 25 '25 02:04 21307369

json中的某个属性的类型定义 只适用于你单独更新这个属性的时候才有效,否则json数据是完整一起写入的 不可能遍历json数据后再格式化写入

liu21st avatar Apr 25 '25 06:04 liu21st