模型变量未更新:Ajax更新后getDay返回旧值问题排查
嘿,这个问题我之前也踩过坑!核心原因其实是Yii框架中每个HTTP请求都会创建一个全新的控制器实例——也就是说,actionChangeDay和actionGetDay是两个完全独立的请求,它们对应的$this->planing_model根本不是同一个对象。
你在actionChangeDay里修改了当前请求实例的curent_day,但这个修改只存在于该请求的内存中,请求结束后控制器和模型实例就被销毁了。等你调用actionGetDay时,系统会重新初始化控制器和模型,自然拿到的还是原来的旧值。
下面给你几个可行的解决方案,按需选择:
1. 持久化修改到数据库(最常用)
如果这个值需要长期保存,或者需要在多个请求/会话中共享,直接把修改保存到数据库是最稳妥的做法:
public function actionChangeDay($new_curent_day){ if(Yii::$app->request->isAjax){ $this->planing_model->curent_day = $new_curent_day; // 新增保存操作,确保修改持久化 if($this->planing_model->save()){ return $this->planing_model->curent_day; } else { // 返回错误信息方便前端调试 return json_encode([ 'error' => '保存失败', 'errors' => $this->planing_model->errors ]); } } }
⚠️ 注意:如果你的模型有验证规则,save()可能会因为验证不通过失败,所以一定要加上错误处理逻辑。
2. 用Session临时存储(适合短期会话)
如果只是需要在当前用户会话中临时保存这个值,不需要写入数据库,可以用Yii的Session组件:
// actionChangeDay 中存储值 public function actionChangeDay($new_curent_day){ if(Yii::$app->request->isAjax){ Yii::$app->session->set('planing_curent_day', $new_curent_day); return $new_curent_day; } } // actionGetDay 中读取值 public function actionGetDay(){ if(Yii::$app->request->isAjax){ // 优先从Session读取,没有则用模型默认值 return Yii::$app->session->get('planing_curent_day', $this->planing_model->curent_day); } }
这种方式的好处是轻量,用户关闭浏览器后Session会自动失效,适合临时状态存储。
3. 前端缓存值(减少请求)
既然是前端发起的请求,也可以在前端直接缓存更新后的值,后续调用getDay时直接用缓存,不用再发请求:
// 全局变量缓存当前day值 let currentDay = null; function changeDay(){ const newDay = $('.owl-item.center .slide_day').text(); $.get('/planing/change-day', {new_curent_day: newDay}, function (data) { console.log(data); // 更新前端缓存 currentDay = data; }); } function getDay(){ // 有缓存直接用,没有再发请求 if(currentDay !== null){ console.log(currentDay); return; } $.get('/planing/get-day', function (data) { console.log(data); currentDay = data; }) }
⚠️ 额外提醒:Ajax是异步的!如果你在调用changeDay()后立刻调用getDay(),可能changeDay的请求还没完成,getDay就已经发起了,这时候也会拿到旧值。可以用Promise保证顺序:
function changeDay(){ return new Promise((resolve) => { const newDay = $('.owl-item.center .slide_day').text(); $.get('/planing/change-day', {new_curent_day: newDay}, function (data) { console.log(data); resolve(data); }); }); } // 调用时确保顺序 changeDay().then(() => { getDay(); });
最后提个小细节:你的变量名拼写是curent_day(少了一个r),建议统一改成current_day,避免后续因为拼写错误踩坑~
内容的提问来源于stack exchange,提问作者markdeitchell

