You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel依赖下拉框:根据选中国家加载关联地区数据

解决Laravel中国家与地区下拉框联动问题

1. 修正后端初始代码问题

你当前create方法里的$regions查询存在两个明显错误:

  • Laravel的where方法语法错误,正确写法是where('字段名', '操作符', 值),你写的'countries_id' == $countries('id')属于PHP语法错误,会先执行布尔判断再把结果传给where。
  • $countries是get()返回的集合对象,不是单个模型实例,无法直接调用id属性。

实现下拉框联动的常规思路是:初始加载页面时只传递所有国家数据,后续通过AJAX根据用户选中的国家动态获取对应地区。修正后的create方法如下:

public function create()
{
    $countries = Countries::orderBy('name')->get();
    return view('admin.cities.create', compact('countries'));
}

2. 新增获取地区的后端接口

添加一个控制器方法,用于接收国家ID并返回关联的地区数据:

use Illuminate\Http\Request;

public function getRegions(Request $request)
{
    $countryId = $request->input('country_id');
    
    // 方式1:直接通过外键查询
    $regions = Regions::where('countries_id', $countryId)->orderBy('name')->get();
    
    // 方式2:利用已设置的Eloquent关联(更符合Laravel规范)
    // 假设Country模型中定义了关联:public function regions() { return $this->hasMany(Regions::class); }
    // $regions = Countries::findOrFail($countryId)->regions()->orderBy('name')->get();
    
    return response()->json($regions);
}

给该方法添加路由:

Route::get('/admin/cities/get-regions', [你的控制器类名::class, 'getRegions'])->name('admin.cities.get-regions');

3. 前端实现联动逻辑

在Blade文件中添加下拉框,并通过JS监听国家选择事件,动态加载对应地区:

<div class="form-group">
    <label for="country_id">国家</label>
    <select id="country_id" name="country_id" class="form-control">
        <option value="">请选择国家</option>
        @foreach($countries as $country)
            <option value="{{ $country->id }}">{{ $country->name }}</option>
        @endforeach
    </select>
</div>

<div class="form-group">
    <label for="region_id">地区</label>
    <select id="region_id" name="region_id" class="form-control">
        <option value="">请先选择国家</option>
    </select>
</div>

<script>
document.getElementById('country_id').addEventListener('change', function() {
    const countryId = this.value;
    const regionSelect = document.getElementById('region_id');
    
    // 清空现有选项并显示加载状态
    regionSelect.innerHTML = '<option value="">加载中...</option>';
    
    if (!countryId) {
        regionSelect.innerHTML = '<option value="">请先选择国家</option>';
        return;
    }
    
    // 发送AJAX请求获取地区数据
    fetch("{{ route('admin.cities.get-regions') }}?country_id=" + countryId)
        .then(res => res.json())
        .then(data => {
            regionSelect.innerHTML = '<option value="">请选择地区</option>';
            data.forEach(region => {
                const option = document.createElement('option');
                option.value = region.id;
                option.textContent = region.name;
                regionSelect.appendChild(option);
            });
        })
        .catch(() => {
            regionSelect.innerHTML = '<option value="">加载失败,请重试</option>';
        });
});
</script>

关于你的疑问

你问能否用变量 = model::where(外键 == 父表ID)的方式实现?当然可以,但需满足两个条件:

  1. 语法正确:Laravel的where方法默认是等于判断,正确写法为where('countries_id', $countryId)。
  2. 父表ID是单个值:比如你拿到单个国家模型实例时,可这样写:
$singleCountry = Countries::find(1); // 获取单个国家模型
$regions = Regions::where('countries_id', $singleCountry->id)->get();

或者利用已设置的Eloquent关联,写法更简洁:

$regions = $singleCountry->regions;

内容的提问来源于stack exchange,提问作者Johannes Jooste

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:25:20