Laravel 9 AJAX加载模态框表单报Undefined variable $errors错误
Laravel 9 加载模态框报
Undefined variable $errors错误修复 问题相关代码
触发模态框的页面代码
<div> <x-button onclick="viewFormAdd()" data-bs-toggle="modal" type="button">Add New Data</x-button> </div> <script> function viewFormAdd() { $.get("{{ route('kategori.create') }}", {}, function(data, status) { $('.viewmodal').html(data).show(); $('#modalCreateKategori').modal('show'); } ); } </script>
模态框视图createKategori.blade.php代码
<x-modal modalId="modalCreateKategori" modalTitle="Tambah Kategori"> <form method="post" action="{{ route('kategori.store') }}" class="formtambah"> @csrf <div class="grid grid-rows-2"> <div> <x-label>Nama Kategori</x-label> <x-input type="text" name="nama_kategori" id="nama_kategori" /> @error('nama_kategori') <small>{{ $message }}</small> @enderror </div> <div class="justify-end items-center"> <x-button type="submit">Simpan</x-button> </div> </div> </form></x-modal>
表单AJAX提交代码
<script> $(document).ready(function() { $('.formtambah').submit(function(e) { e.preventDefault(); $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); $.ajax({ type: "post", url: $(this).attr('action'), data: $(this).serialize(), dataType: "json", success: function(response) { if (response.tersimpan) { Swal.fire({ position: 'center', icon: 'success', title: 'Tersimpan!', text: response.tersimpan, showConfirmButton: false, timer: 1500 }) $('.btn-close').click(); dataKategori(); } }, error: function(xhr, thrownError) { alert(xhr.status + "\n" + xhr.responseText + "\n" + thrownError); } }); return false; }); });</script>
控制器代码
public function create() { return view('kategori.createKategori'); } public function store(KategoriRequest $request) { $kategori = new Kategoris; $kategori->namakat = $request->nama_kategori; $kategori->save(); $msg = [ 'tersimpan'=> 'Produk baru berhasil tersimpan!' ]; return response()->json($msg); }
表单验证类代码
class KategoriRequest extends FormRequest{ public function authorize() { return true; } public function rules() { return [ 'nama_kategori' => 'required' ]; } public function messages() { return[ 'nama_kategori.required' => 'Maaf, nama kategori harus diisi' ]; } }
问题现象
点击按钮加载模态框时接口返回500错误,报错信息:
Undefined variable $errors (View: C:\xampp\htdocs\newsinartimur_laravel_9\resources\views\kategori\createKategori.blade.php)
浏览器抓包显示请求地址为http://localhost:8000/api/kategori/create,返回500状态码。删除视图中@error相关的验证提示代码后,模态框和表单可正常运行。
故障原因
你的kategori.create路由被定义在api.php路由文件中,默认走API路由组。Laravel的API路由组默认不会加载StartSession、ShareErrorsFromSession这两个Web中间件,而Blade的@error指令依赖ShareErrorsFromSession中间件向视图注入的$errors变量,API路由下没有这个变量,就会触发未定义变量错误。
修复方案
选择任意一种方案即可:
- 方案1(推荐):将
kategori相关的资源路由从api.php迁移到web.php路由文件。这类需要返回视图、依赖session、表单验证错误提示的交互逻辑属于Web场景,走Web中间件栈后会自动加载session相关逻辑,$errors变量会自动注入视图,@error指令可正常工作。 - 方案2:如果必须将该路由放在API路由下,手动给对应路由/路由组补充缺失的中间件。打开
app/Http/Kernel.php,在api中间件组中添加如下两个中间件:
protected $middlewareGroups = [ 'api' => [ // 原有API中间件保持不动 \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, ], ];
注意:API路由默认设计为无状态,添加session相关中间件会破坏API的无状态特性,非必要不选这个方案。
- 方案3(临时兼容):在视图中先判断
$errors变量是否存在再输出错误,仅用于临时规避问题,不推荐长期使用:
@if(isset($errors) && $errors->has('nama_kategori')) <small>{{ $errors->first('nama_kategori') }}</small> @endif
额外提示:当前控制器中存储成功的提示文案为
Produk baru berhasil tersimpan!(新产品保存成功),和当前分类(kategori)存储逻辑不匹配,建议修改为对应分类的提示文案避免误导。
内容的提问来源于stack exchange,提问作者SinchanMan
相关产品推荐
相关产品推荐

