如何从MVC控制器正确获取JSON数据?返回含HTML问题排查
问题:AJAX请求返回包含JSON的完整HTML页面,而非预期的纯JSON数据
我通过以下jQuery AJAX代码向MVC控制器请求数据:
$(document).on("click", "#btn-register", function (event) { event.preventDefault(); $.ajax({ url: baseUrl() + "/users/register", type: "POST", dataType: "JSON", data: { name: $("#name").val(), email: $("#email-address").val(), password: $("#password").val(), confirm: $("#confirm-password").val(), }, success: function (data) { console.log(data); }, error: function (message) { console.log(message.responseText); }, }); });
对应的PHP MVC控制器代码:
public function register () { $result = []; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS); $data = [ 'name' => trim($_POST['name']), 'email' => trim($_POST['email']), 'password' => trim($_POST['password']), 'confirm_password' => trim($_POST['confirm']), 'name_error' => '', 'email_error' => '', 'password_error' => '', 'confirm_password_error' => '' ]; $data['name_error'] = (empty($data['name'])) ? 'Please enter name' : ''; $data['confirm_password_error'] = (empty($data['confirm_password'])) ? 'Please confirm password' : ''; if (empty($data['email'])) $data['email_error'] = 'Please enter email'; else if ($this->user->findUserByEmail($data['email']) === true) $data['email_error'] = 'Email is already taken'; if (empty($data['password'])) $data['password_error'] = 'Please enter a password'; else if (strlen($data['password']) < self::$password_length) $data['password_error'] = 'Password must be at least ' . self::$password_length . ' characters long'; else if ($data['password'] != $data['confirm_password']) $data['password_error'] = 'Password did not match'; if ( empty($data['name_error']) && empty($data['email_error']) && empty($data['password_error']) && empty($data['confirm_password_error'])) { $result['status'] = 'valid inputs'; echo json_encode($result); } } else { $data = [ 'name' => '', 'email' => '', 'password' => '', 'confirm_password' => '', 'name_error' => '', 'email_error' => '', 'password_error' => '', 'confirm_password_error' => '' ]; } $this->view('users/register', $data); }
点击#btn-register按钮后,error回调输出包含{"status":"valid inputs"}的完整HTML页面,而非仅JSON数据。
原因分析
核心问题是控制器输出JSON后未终止脚本执行:当输入验证通过时,你通过echo json_encode($result)输出了JSON字符串,但代码继续执行到末尾的$this->view('users/register', $data),这会渲染并输出整个注册页面的HTML代码。最终响应内容是JSON字符串 + HTML代码的混合体,jQuery的dataType: "JSON"无法解析这种混合内容,因此触发error回调。
解决方法
1. 输出JSON后立即终止脚本
在echo json_encode($result);之后添加exit;或die();,阻止后续代码执行,确保仅输出JSON数据:
if ( empty($data['name_error']) && empty($data['email_error']) && empty($data['password_error']) && empty($data['confirm_password_error'])) { $result['status'] = 'valid inputs'; echo json_encode($result); exit; // 终止脚本,不再执行后续的view渲染 }
2. (可选)设置正确的响应头
为了更规范地告诉客户端返回的是JSON数据,在输出JSON之前添加Content-Type响应头:
if ( empty($data['name_error']) && empty($data['email_error']) && empty($data['password_error']) && empty($data['confirm_password_error'])) { header('Content-Type: application/json'); // 设置JSON响应头 $result['status'] = 'valid inputs'; echo json_encode($result); exit; }
这样修改后,AJAX请求会收到纯JSON数据,触发success回调并正确解析数据。
内容的提问来源于stack exchange,提问作者Jhay Lawrence
相关产品推荐
相关产品推荐

