CodeIgniter同控制器内加载视图并传递数据的实现问题
解决CodeIgniter Ajax登录后加载视图并传递数据的问题
你遇到的核心问题是Ajax异步请求的处理逻辑不对:当你用Ajax提交表单时,控制器直接加载视图的内容会返回给Ajax的响应对象,而不是自动替换当前页面。另外你还漏了把数据传递给视图,同时SQL语句存在注入风险,我们一步步来修复:
1. 修复控制器的validate_LogIn方法
首先,你需要修改控制器逻辑,这里提供两种常用方案:
方案一:返回视图HTML,用JS替换页面内容
修改控制器,把视图渲染后的HTML返回给Ajax,同时传递用户数据:
<?php class logInCon extends CI_Controller { public function login() { $this->load->view("Login"); } public function validate_LogIn() { $uname = $this->input->post('uname'); $pass = $this->input->post('pass'); $this->load->model("accsModel"); $data = $this->accsModel->logInCheck($uname, $pass); $check = $data['verified']; if ($check <= 0) { echo json_encode(['status' => 'error', 'message' => "Not a valid member"]); } else { // 获取用户数据并传递给视图 $data['logged'] = $this->accsModel->getUser($uname, $pass); // 第三个参数设为true,返回视图的HTML字符串而不是直接输出 $html = $this->load->view('comms', $data, true); echo json_encode(['status' => 'success', 'html' => $html]); } } } ?>
方案二:返回重定向地址,让页面跳转
如果更倾向于传统的页面跳转模式,可以把用户信息存入Session,然后让前端跳转到新页面加载视图:
<?php class logInCon extends CI_Controller { public function login() { $this->load->view("Login"); } public function validate_LogIn() { $uname = $this->input->post('uname'); $pass = $this->input->post('pass'); $this->load->model("accsModel"); $data = $this->accsModel->logInCheck($uname, $pass); $check = $data['verified']; if ($check <= 0) { echo json_encode(['status' => 'error', 'message' => "Not a valid member"]); } else { // 将用户信息存入Session,方便后续页面调用 $user_data = $this->accsModel->getUser($uname, $pass); $this->session->set_userdata('logged_user', $user_data); echo json_encode(['status' => 'success', 'redirect_url' => base_url('logInCon/comms')]); } } // 新增加载comms视图的独立方法 public function comms() { $data['logged'] = $this->session->userdata('logged_user'); $this->load->view('comms', $data); } } ?>
2. 修复Model的SQL注入风险
你的getUser方法直接将用户输入拼进SQL,存在严重的注入漏洞,改成CodeIgniter的查询绑定方式:
<?php class accsModel extends CI_Model { public function getBps() { $query = $this->db->get('bps'); return $query->result(); } public function getUser($uname, $psswrd) { // 使用?作为占位符,通过数组传递参数,自动防止SQL注入 $sql = "SELECT `bps`.*, `users`.bps_id FROM `bps` LEFT JOIN `users` ON `bps`.id = `users`.bps_id AND `users`.`uname` = ? AND `users`.`pwd` = ? WHERE `users`.bps_id != '' OR `users`.bps_id IS NOT NULL"; $query = $this->db->query($sql, [$uname, $psswrd]); return $query->result(); } public function logInCheck($uname, $psswrd) { $this->db->select('COUNT(*) AS verified'); $this->db->where('uname', $uname); $this->db->where('pwd', $psswrd); $this->db->limit(1); return $this->db->get('users')->row_array(); } } ?>
3. 修复前端Ajax的响应处理逻辑
根据上面的控制器方案,修改前端JS代码:
对应方案一的JS修改
<body> <div class="container"> <div class="row"> <div class="LogForm"> <div class="col-md-12"> <input type="text" id="bpCode" name="bpCode"> </div> <div class="col-md-12"> <input type="password" id="pass" name="pass"> </div> <div class="btn"> <span id="emptyF" hidden style="color:red;"></span> <button id="submit" class="btn btn-info btn-lg btn-block">Login</button> <span id="result"></span> </div> </div> </div> </div> <script type="text/javascript"> $(document).ready(function() { $("#submit").click(function(e) { e.preventDefault(); // 阻止按钮默认提交行为 var uname = $('#bpCode').val(); var pass = $('#pass').val(); if(uname == "" || pass =="") { $("#emptyF").attr("hidden", false).html("Please fill in the form"); } else { $("#emptyF").attr("hidden", true); $.ajax({ type: "POST", url: "<?php echo base_url('logInCon/validate_LogIn'); ?>", data: { uname : uname, pass : pass }, dataType: 'json', // 指定接收JSON格式响应 success: function(response) { if(response.status === 'error') { $("#result").html(response.message).css('color', 'red'); } else { // 替换整个页面内容为新视图的HTML $('body').html(response.html); } } }); } }); }); </script> </body>
对应方案二的JS修改
<body> <div class="container"> <div class="row"> <div class="LogForm"> <div class="col-md-12"> <input type="text" id="bpCode" name="bpCode"> </div> <div class="col-md-12"> <input type="password" id="pass" name="pass"> </div> <div class="btn"> <span id="emptyF" hidden style="color:red;"></span> <button id="submit" class="btn btn-info btn-lg btn-block">Login</button> <span id="result"></span> </div> </div> </div> </div> <script type="text/javascript"> $(document).ready(function() { $("#submit").click(function(e) { e.preventDefault(); // 阻止按钮默认提交行为 var uname = $('#bpCode').val(); var pass = $('#pass').val(); if(uname == "" || pass =="") { $("#emptyF").attr("hidden", false).html("Please fill in the form"); } else { $("#emptyF").attr("hidden", true); $.ajax({ type: "POST", url: "<?php echo base_url('logInCon/validate_LogIn'); ?>", data: { uname : uname, pass : pass }, dataType: 'json', success: function(response) { if(response.status === 'error') { $("#result").html(response.message).css('color', 'red'); } else { // 跳转到指定页面加载视图 window.location.href = response.redirect_url; } } }); } }); }); </script> </body>
4. 补充注意事项
- 如果使用方案二,需要确保已经加载了Session库:在
config/autoload.php中添加$autoload['libraries'] = array('session'); - CodeIgniter加载视图时不需要加
.php后缀,所以$this->load->view('comms')即可,不用写comms.php - 重要提醒:当前代码明文存储密码非常不安全,建议使用CodeIgniter的
password_hash()加密密码,登录时用password_verify()验证
内容的提问来源于stack exchange,提问作者Edhans
相关产品推荐
相关产品推荐

