top-think / think-orm

Think ORM——the PHP Database&ORM Framework
Apache License 2.0
413 stars 171 forks source link

[3.0.25] 模型`column`和`value`默认经过获取器存在兼容性中断问题 #628

Closed NHZEX closed 5 days ago

NHZEX commented 1 week ago

更大的隐患:

  1. column重命名字段行为导致意外调用当前模型类型转换的情况。
  2. column原有的查询结果是输出原始数据,这个更新导致变化类型转换后的数据,可能会到原有代码产生破坏行为。

ps: value方法应该也存在一样的问题。

---- 原始内容 ----

触发必须条件模型:convertNameToCamel = true

$result = (new AdminUser())
    ->alias('u')
    ->limit(5)
    ->column([
        'u.id' => 'id',
        'u.create_time' => 'createTime',
        'u.update_time' => 'updateTime',
    ]);

var_dump($result);

结果:只要是驼峰命名都变成 null

array(2) {
  [0]=>
  array(3) {
    ["id"]=>
    int(1)
    ["createTime"]=>
    NULL
    ["updateTime"]=>
    NULL
  }
  [1]=>
  array(3) {
    ["id"]=>
    int(2)
    ["createTime"]=>
    NULL
    ["updateTime"]=>
    NULL
  }
}

ps:有没有考虑妥善解决更新导致频繁的兼容性中断问题,最近几个版本频繁发生🤣

liu21st commented 1 week ago

你开启了convertNameToCamel 然后又做了一个字段映射 不是多此一举么

NHZEX commented 1 week ago

你开启了convertNameToCamel 然后又做了一个字段映射 不是多此一举么

column输出是数组,不是一直不支持convertNameToCamel么,我重新测试老版本24是不支持自动驼峰,必须手动转换,25版本确实支持自动转换了。这相当于BC中断了。

而且发现另一个问题:

$result = (new AdminUser())
    ->alias('u')
    ->limit(5)
    ->column([
        'u.id' => 'id',
        'u.create_time',
        'u.update_time',
        'u.update_time' => 'aaaBbbCcc',
    ]);

var_dump($result);

结果:aaaBbbCcc直接变为null

array(2) {
  [0]=>
  array(4) {
    ["id"]=>
    int(1)
    ["createTime"]=>
    int(1718970059)
    ["updateTime"]=>
    int(1725270718)
    ["aaaBbbCcc"]=>
    NULL
  }
  [1]=>
  array(4) {
    ["id"]=>
    int(2)
    ["createTime"]=>
    int(1725291177)
    ["updateTime"]=>
    int(1725291269)
    ["aaaBbbCcc"]=>
    NULL
  }
}
liu21st commented 1 week ago

数据库查询的字段必须是下划线的 不能是驼峰

NHZEX commented 1 week ago

数据库查询的字段必须是下划线的 不能是驼峰

明白了,开了convertNameToCamel别名映射也要下划线,让orm自动转。

(new AdminUser())
    ->alias('u')
    ->limit(5)
    ->column([
        'u.id' => 'id',
        'u.create_time',
        'u.update_time',
        'u.update_time' => 'aaa_bbb_ccc',
    ]);
array(4) {
    ["id"]=>
    int(1)
    ["createTime"]=>
    int(1718970059)
    ["updateTime"]=>
    int(1725270718)
    ["aaaBbbCcc"]=>
    int(1725270718)
  }

那这个更改导致column的兼容中断如何考虑?

  1. 如果不做改变那全部column中用到驼峰手动映射都得改一遍。
  2. 还有类型问题,原来查询都是原始值,现在变成被模型转换后的值,产生的兼容问题很多。

还有一个隐患,column之前一直是不调用模型的类型转换的,字段随意命名是没问题的,但现在命名得考虑到冲突,多表聚合或者需要别名转换时。 例子:比如模型A和模型B都有一个status字段,都在模型中实现各自的status转Enum。当调用A模型的column聚合A+B的数据特定字段(A.id => id, B.status => status),那实出结果的B.status会被A模型的status以为转换,那结果就是完全错了。那这种情况下定义别名时必须考虑字段不能与模型的类型转换定义冲突。