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

在更新或删除时模型实例存在时则插入主键限制条件

Open chuoke opened this issue 3 years ago • 8 comments

老版有个问题,如果有全局查询范围或是添加了额外的条件,则会丢失主键条件 如:

$model = Model::find(1);
$model->inc('field', 2)->where([ 'other' => 'value' ])->update();

这个更新的SQL会变成 update model set field = field + 2 where other = value,如果有个全局查询范围也会导致这样的情况,这样的行为结果有点反直觉反人类。

我不知道这样改下有没有其它影响,可以当作一个改进提议。

chuoke avatar Feb 16 '22 05:02 chuoke

示例改了下,之前那个应该是全局查询范围导致的。

chuoke avatar Feb 16 '22 06:02 chuoke

第二行的更新跟第一次的查询有关系吗.

在这里model就是一个确定的数据库的一行,model对象就已经是数据库中明确的指定的其中一行了. 这里model不是用来操作数据库的query.

你的意思是不是这样,

$query = User::where('id',1);  // 注意没有进行查询
$query->where('other','condiition')->update(['field'=>1]);

augushong avatar Feb 16 '22 06:02 augushong

大概是这样的,为了数据不会更新出错,当我用了低级的解决方案,如果支持这样用,不是更好, 比如加/减某个字段,我要限制不会超范围:

// 关于 $model 的其它逻辑
$model->dec('num')->where('num', '>', 1000)->update();
// 关于 $model 的其它逻辑

因为存在并发或多个逻辑会对这个字段加/减,所以简单的加了个条件来做限制。

chuoke avatar Feb 16 '22 06:02 chuoke

你换成save试试行不行吧, update的方法,应该是模型类直接调用的,模型实例是不应该调用的,模型实例应该用save

augushong avatar Feb 16 '22 06:02 augushong

save 不行,试过了

chuoke avatar Feb 16 '22 06:02 chuoke

update的方法,应该是模型类直接调用的,模型实例是不应该调用的,模型实例应该用save

其实是支持使用的,只是不是很友好,我改的那个,还没有全面的测试,但是我感觉大差不差了

chuoke avatar Feb 16 '22 06:02 chuoke

^-^,那就是存在这样的用法的, 模型实例就是数据库中明确的一行了,不应该在家条件了.

要不你就试试事务+lock方法, 或者纯Db操作.

augushong avatar Feb 16 '22 06:02 augushong

我现在就是再追加了个 $model->getWhere() 条件,虽然感觉有点怪,但是可以解决,整个逻辑阅读起来,比改用Db操作顺畅点。

另外哦,目前发现,incdec 方法,如果有自定义的全局查询范围,好像是直接用不了的 (比较忙没有详细测试 😶)。

chuoke avatar Feb 16 '22 06:02 chuoke

不应该存在你这样的用法吧,你已经知道了数据的id,查出来了这条数据,为什么更新的时候,还要再加入一个条件呢.

另外,update是Db方法,不是模型方法,模型不应当使用update来更新数据,应该用save

至于使用什么方法,我觉得既然官方提供了这个模型的update方法,那就说明可以使用,为什么强制别人一定要用save方法呢?

AnkoGo123 avatar Nov 07 '22 00:11 AnkoGo123

提供了update方法,自然是可以使用的,但你得按文档的用法来啊,不是按自己的直觉来。

总有人把自己的经验带到框架的使用方法里,这样是不对的。

你要是按tp3的使用经验来用tp6,按你的说法,到处都是bug的。

你可以看看tp3的文档,我估计它的设计理念完全符合你的认知。

基本的地orm封装就这几个操作,都是这样表现的。

augushong avatar Nov 07 '22 00:11 augushong