CakePHP 3.4+jQuery Ajax开发遇问题:弃用警告与重复返回
我来帮你解决这两个问题,一步步来:
问题1:Controller::$layout 弃用警告
这个警告是因为CakePHP 3.4开始不再推荐直接通过$this->layout设置布局,官方要求改用viewBuilder()的方法来操作视图配置。
修复步骤:
- 如果你在控制器里手动设置了布局(比如
$this->layout = 'default';),把它改成:$this->viewBuilder()->setLayout('default'); - 如果没手动设置布局但还是出现警告,检查一下你的控制器是否继承了某个父控制器,或者有没有组件在调用旧的
$layout写法,把这些地方都替换成viewBuilder()->setLayout()的形式。
问题2:Ajax请求后页面重复返回同一个div
这个问题的核心原因是:你的index视图会输出全部内容(包括foreach循环和#show div),当Ajax请求index动作时,返回的是整个视图的HTML,然后你用$("#show").html(result)把整个视图内容塞进#show里,导致#show内部又嵌套了一个#show,造成重复。
这里有两种常用的修复方案:
方案1:创建专门的Ajax处理动作
这种方式更清晰,把页面渲染和Ajax数据返回分开:
在控制器中新增
getPosts动作:public function getPosts() { // 推荐用getData()替代data(),是CakePHP 3.4+的标准写法 $id = $this->request->getData('idString'); $posts = $this->Posts->find('all', [ 'conditions' => ['Animal_id' => $id] ]); $this->set(compact('posts')); // 关闭布局,只返回需要的内容 $this->viewBuilder()->setLayout(false); // 渲染一个专门的元素视图 return $this->render('Elements/post_list'); }创建元素视图文件:
在src/Template/Elements/目录下新建post_list.ctp,只放列表内容:<?php foreach($posts as $post):?> <li><?= $post->title . ', ' . $post->text; ?></li> <?php endforeach ?>修改前端Ajax的URL:
把请求地址指向新的getPosts动作:url: "<?php echo \Cake\Routing\Router::url(['controller' => 'MyControllerName', 'action' => 'getPosts']); ?>",
这样Ajax请求返回的就只有列表内容,塞进#show里不会出现重复嵌套的问题。
方案2:在现有视图中判断Ajax请求
如果不想新增动作,可以在index视图里根据请求类型决定输出内容:
修改控制器的
index动作:public function index() { $id = $this->request->getData('idString'); $posts = $this->Posts->find('all', [ 'conditions' => ['Animal_id' => $id] ]); $this->set(compact('posts')); // 如果是Ajax请求,关闭布局 if ($this->request->is('ajax')) { $this->viewBuilder()->setLayout(false); } }修改
index视图文件:<?php if (!$this->request->is('ajax')): ?> <!-- 非Ajax请求时显示完整页面结构 --> <div id="show"> <?php foreach($posts as $post):?> <li><?= $post->title . ', ' . $post->text; ?></li> <?php endforeach ?> </div> <?php else: ?> <!-- Ajax请求时只输出列表内容 --> <?php foreach($posts as $post):?> <li><?= $post->title . ', ' . $post->text; ?></li> <?php endforeach ?> <?php endif; ?>
这样当Ajax请求index动作时,返回的只有列表部分,不会包含#show div,自然就不会重复了。
另外补充一下:你把$_POST["idString"]改成$this->request->data('idString')是对的,不过更推荐用$this->request->getData('idString'),这是CakePHP 3.4及以后版本的标准获取POST数据的方法。
内容的提问来源于stack exchange,提问作者user7362769

