save 时怎么保留查询时的 where 条件(乐观锁实现)

请不要忘记看标题

怎么保留

// $model = X::query()->where('field1','a')->where('field2','b')->first();
// 更新一下 :
$model = X::query()->where('pk','value')->where('version','uuid')->first();
$model->field = 'abc';
$model->save();

得到的SQL是

UPDATE x set field = 'abc' where pk = 'id';
-- 期望sql👇
-- update x set field = 'abc' where pk = 'id' and version = 'uuid'

查询时的where条件丢失。Model::where()->update()又会不触发模型事件

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
最佳答案
// 在你的模型中覆写这个方法
protected function performUpdate(Builder $query)
{
    $query->where('version', $this->version)
    return parent::performUpdate($query)
}

覆写这个方法可一做到,然后测试下,这个方法追踪后只找到了save()方法在调用,影响范围可控

5个月前 评论
cevin (楼主) 5个月前
cevin (楼主) 5个月前
anniversary (作者) 5个月前
cevin (楼主) 5个月前
讨论数量: 7

你要查询条件干啥 更新时已经保留了主键筛选啊 主键确定了 其他什么条件都没有用啊

6个月前 评论
cevin (楼主) 6个月前

你想要得到什么样的sql

6个月前 评论
cevin (楼主) 6个月前
$model->where('version',$model->version)->update(['field3'=>'abc','version'=>$model->version+1])
6个月前 评论
cevin (楼主) 6个月前

没理解啊

6个月前 评论
cevin (楼主) 6个月前
lddtime 6个月前
monanxiao (作者) 6个月前
cevin (楼主) 5个月前
// 在你的模型中覆写这个方法
protected function performUpdate(Builder $query)
{
    $query->where('version', $this->version)
    return parent::performUpdate($query)
}

覆写这个方法可一做到,然后测试下,这个方法追踪后只找到了save()方法在调用,影响范围可控

5个月前 评论
cevin (楼主) 5个月前
cevin (楼主) 5个月前
anniversary (作者) 5个月前
cevin (楼主) 5个月前
小烦

....你指的模型事件是指啥?observer? 如果是监听者的话,update要触发observer 触发模型事件必须先get() 或 first() 比如:

//这个是会触发observer 
Tags::query()->where('tag', '签到任务')->first()->update(['title'=>'巴拉巴拉']);
//这个不会触发
Tags::query()->where('tag', '签到任务')->update(['title'=>'巴拉巴拉']);
5个月前 评论

重写一下 model 中的 save 方法,应该能达到你想要的效果。: )


public function save(array $options = [],$otherWhere=[])
    {
        $query = $this->newModelQuery();

       $otherWhere && $query->where($otherWhere)

        // If the "saving" event returns false we'll bail out of the save and return
        // false, indicating that the save failed. This provides a chance for any
        // listeners to cancel save operations if validations fail or whatever.
        if ($this->fireModelEvent('saving') === false) {
            return false;
        }

        // If the model already exists in the database we can just update our record
        // that is already in this database using the current IDs in this "where"
        // clause to only update this model. Otherwise, we'll just insert them.
        if ($this->exists) {
            $saved = $this->isDirty() ?
                        $this->performUpdate($query) : true;
        }

        // If the model is brand new, we'll insert it into our database and set the
        // ID attribute on the model to the value of the newly inserted row's ID
        // which is typically an auto-increment value managed by the database.
        else {
            $saved = $this->performInsert($query);

            if (! $this->getConnectionName() &&
                $connection = $query->getConnection()) {
                $this->setConnection($connection->getName());
            }
        }

        // If the model is successfully saved, we need to do a few more things once
        // that is done. We will call the "saved" method here to run any actions
        // we need to happen after a model gets successfully saved right here.
        if ($saved) {
            $this->finishSave($options);
        }

        return $saved;
    }
5个月前 评论
cevin (楼主) 5个月前
superSnail (作者) 5个月前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!