Laravel Blade三级依赖下拉菜单Thana层级AJAX POST请求报500错误
三级联动下拉菜单500错误问题排查与修复
问题背景
实现的三级联动逻辑为:国家名称->城市名称->Thana名称,其中城市依赖国家、Thana依赖城市。目前国家联动城市逻辑正常,但切换城市加载Thana时返回500内部服务错误,报错信息如下:
POST http://localhost/rul/ecom/get-thana 500 (Internal Server Error)
错误原因定位
500错误来源于ThanaController的get_thana方法存在空对象调用问题:
$city_info = City::where('name', $request->city_name)->first(); // 此处未判断$city_info是否存在,当查询不到对应城市时,$city_info为null $thanas = Thana::where('city_id', $city_info->id)->get(); // 调用null的id属性直接触发致命错误,返回500状态码
可能的触发场景包括:
- 城市名称存在多语言翻译,前端提交的名称和数据库存储的原始名称不匹配
- 存在重名城市导致查询到的结果不是预期数据
- 提交的城市名称存在特殊字符/空格,和数据库存储内容不一致
修复方案
方案1:快速修复现有逻辑(保留用name查询的写法)
给get_thana方法加空判断,避免空对象调用即可:
public function get_thana(Request $request) { // 补充状态过滤和空判断,和国家查询逻辑保持一致 $city_info = City::where('status',1)->where('name', $request->city_name)->first(); if(!$city_info){ return json_encode(''); } $thanas = Thana::where('city_id', $city_info->id)->get(); $html = ''; foreach ($thanas as $row) { $html .= '<option value="' . $row->name . '">' . $row->getTranslation('name') . '</option>'; } return json_encode($html); }
方案2:最优修复(改为用ID关联,彻底避免名称匹配问题)
推荐所有下拉选项的value存储主键ID,而非名称,既提升查询性能,也能彻底避免名称匹配失败的问题,修改步骤如下:
- 修改
CityController的get_city方法,option的value改为城市ID:
public function get_city(Request $request) { $country_info = Country::where('status',1)->where('name', $request->country_name)->first(); if(!$country_info){ return json_encode(''); } $cities = City::where('country_id', $country_info->id)->get(); $html = ''; foreach ($cities as $row) { // value改为存储城市ID $html .= '<option value="' . $row->id . '">' . $row->getTranslation('name') . '</option>'; } return json_encode($html); }
- 修改
ThanaController的get_thana方法,直接用ID查询城市:
public function get_thana(Request $request) { // 直接用主键ID查询,性能更高,不会出现匹配失败问题 $city_info = City::where('status',1)->find($request->city_id); if(!$city_info){ return json_encode(''); } $thanas = Thana::where('city_id', $city_info->id)->get(); $html = ''; foreach ($thanas as $row) { $html .= '<option value="' . $row->id . '">' . $row->getTranslation('name') . '</option>'; } return json_encode($html); }
- 修改对应AJAX传参,
get_thana的传参键改为city_id:
function get_thana(cityId) { $.ajax({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, url: "{{route('get-thana')}}", type: 'POST', data: { city_id: cityId }, success: function (response) { var obj = JSON.parse(response); if(obj != '') { $('[name="thana"]').html(obj); AIZ.plugins.bootstrapSelect('refresh'); } } }); }
额外优化建议
- 所有控制器方法请用
return返回响应,不要用echo,符合Laravel的开发规范 - 每次切换上级选项时,清空下级选项的已有值,避免旧数据残留
内容的提问来源于stack exchange,提问作者Arafat Rahman
相关产品推荐
相关产品推荐

