Laravel iframe表单提交POST路由时控制器整页重定向失效
问题原因
两个问题导致无法触发整页跳转:
- 表单配置了
target="admin-login",所有提交后的响应默认只会在对应id的隐藏iframe内渲染,后端直接返回重定向的话,跳转仅作用在iframe上下文,不会影响父页面。 - 现有
dologin方法中认证成功后的Redirect::to()调用没有加return,该行代码本身就不会返回重定向响应,逻辑本身存在bug。
修复方案
推荐保留iframe无刷新提交的体验,通过前后端配合实现父页面跳转,步骤如下:
1. 修正后端dologin逻辑
认证成功后不再直接返回重定向响应,统一返回JSON格式结果,将跳转地址返回给前端处理,同时补全响应的return语句,修正错误提示为中文:
public function dologin(){ $email = \request()->email; $pass = \request()->password; $admin = new Admins(); $admin_data = $admin->getAdmin($email); if($admin_data <> null){ if(md5($pass) === $admin_data->password){ session()->put('admin', [ 'admin_id' => $admin_data->id, 'admin_name' => $admin_data->name, 'admin_email' => $admin_data->email, 'admin_mobile' => $admin_data->mobile ]); // 认证成功返回标识和目标跳转地址 return json_encode([ 'succ' => true, 'redirect_url' => URL::to('/').'/admin/main' ]); }else{ return json_encode(['succ' => false, 'cause' => '用户名或密码错误']); } }else{ return json_encode(['succ' => false, 'cause' => '未找到对应邮箱账号']); } }
2. 增加前端iframe响应监听逻辑
监听隐藏iframe的加载完成事件,解析后端返回的JSON结果,登录成功时通过parent.location触发父页面整页跳转,失败时展示错误提示,同时补全提交按钮的加载状态交互:
document.addEventListener('DOMContentLoaded', function() { const loginIframe = document.getElementById('admin-login'); const errorContainer = document.querySelector('.color-error-msg'); const submitBtn = document.getElementById('sign_in_submit'); const progressText = submitBtn.querySelector('.indicator-progress'); const btnLabel = submitBtn.querySelector('.indicator-label'); // 表单提交时触发按钮加载状态 document.getElementById('login-form').addEventListener('submit', function() { errorContainer.textContent = ''; submitBtn.disabled = true; progressText.style.display = 'inline-block'; btnLabel.style.display = 'none'; }); // iframe加载完成即拿到后端响应 loginIframe.addEventListener('load', function() { // 恢复按钮初始状态 submitBtn.disabled = false; progressText.style.display = 'none'; btnLabel.style.display = 'inline-block'; try { // 读取iframe内的响应内容 const responseContent = loginIframe.contentDocument.body.innerText; const result = JSON.parse(responseContent); if(result.succ) { // 登录成功,父页面整页跳转至后台 window.top.location.href = result.redirect_url; } else { // 展示错误提示,3秒后自动清除 errorContainer.textContent = result.cause; setTimeout(() => errorContainer.textContent = '', 3000); } } catch (err) { errorContainer.textContent = '登录请求异常,请刷新后重试'; } }); });
简化方案(无无刷新需求时使用)
如果不需要保留无刷新提交的体验,可以直接删除表单上的target="admin-login"属性,同时将dologin方法认证成功后的逻辑改为return redirect(URL::to('/').'/admin/main');,表单提交后后端返回的重定向会直接作用在当前页面,实现整页跳转,不需要编写额外的前端JS逻辑。
内容的提问来源于stack exchange,提问作者Hasan Ali Eed Alabbasi
相关产品推荐
相关产品推荐

