Laravel Nova实现关联筛选:将Manufacturer筛选器值传递给Model筛选器
实现Laravel Nova中Manufacturer与Model筛选器的联动
我之前也碰到过这个需求,要实现Nova里筛选器的联动,得搞定两个核心点:后端能根据已选厂商动态返回对应型号,还有前端在厂商筛选变化时自动刷新型号筛选器的选项。下面分版本给你具体解决方案:
方案一:Laravel Nova 4+(推荐,原生支持依赖筛选)
Nova 4及以上版本自带筛选器依赖功能,直接用这个特性最省心:
1. 修改Model筛选器,添加依赖配置
在Model筛选器类里,加上$dependsOn属性,指定它依赖的Manufacturer筛选器(默认key是类名的蛇形命名manufacturer):
class Model extends Filter { public $component = 'select-filter'; // 指定依赖的筛选器key public $dependsOn = ['manufacturer']; // 保留原有的apply方法不变 public function apply(Request $request, $query, $value) { return $query->whereHas('product', function ($query) use ($value) { $query->where('model', $value); }); } public function options(Request $request) { // 初始化Product查询 $query = Product::select('model') ->withoutGlobalScopes() ->withoutTrashed() ->groupBy('model') ->orderBy('model'); // 从request中获取已选的厂商值 $selectedManufacturer = $request->input('filters.manufacturer'); // 如果有选中的厂商,添加筛选条件 if ($selectedManufacturer) { $query->where('manufacturer', $selectedManufacturer); } return $query->pluck('model') ->mapWithKeys(function ($model) { return [$model => strtolower($model)]; }) ->toArray(); } }
2. 自定义筛选器名称的适配(可选)
如果你给Manufacturer筛选器自定义了名称(通过name()方法),得同步修改Model筛选器的依赖配置和取值逻辑:
比如Manufacturer筛选器自定义了name:
class Manufacturer extends Filter { public function name() { return 'custom_manufacturer'; } // 其他代码不变 }
那Model筛选器里要调整成这样:
public $dependsOn = ['custom_manufacturer']; // 在options方法中获取值 $selectedManufacturer = $request->input('filters.custom_manufacturer');
配置完之后,用户选厂商的时候,Nova会自动触发Model筛选器的选项重新加载,后端会根据选中的厂商返回对应的型号列表。
方案二:Laravel Nova 3及以下版本(自定义前端组件)
如果用的是Nova 3或更早版本,没有内置依赖筛选支持,就得自己写Vue组件实现联动:
1. 创建自定义筛选器组件
在resources/js/components/filters/DependentSelectFilter.vue里写组件代码:
<template> <select-filter :field="field" :value="value" @input="handleInput" ></select-filter> </template> <script> import SelectFilter from '@nova/filters/SelectFilter' export default { components: { SelectFilter }, props: ['field', 'value', 'resourceName', 'resourceId'], watch: { // 监听厂商筛选器的变化 '$root.$filters.manufacturer': function(newVal) { // 重新加载当前筛选器的选项 this.field.options = this.fetchOptions(newVal) } }, methods: { handleInput(value) { this.$emit('input', value) }, async fetchOptions(manufacturer) { const response = await Nova.request().get(`/nova-api/reviews/filters/${this.field.key}/options`, { params: { filters: { manufacturer } } }) return response.data } }, mounted() { // 初始化时加载默认选项 this.fetchOptions(this.$root.$filters.manufacturer).then(options => { this.field.options = options }) } } </script>
2. 注册自定义组件
在resources/js/app.js里注册这个组件:
Nova.booting((Vue, router) => { Vue.component('dependent-select-filter', require('./components/filters/DependentSelectFilter.vue').default) })
3. 修改Model筛选器的组件类型
把Model筛选器的$component改成自定义组件:
class Model extends Filter { public $component = 'dependent-select-filter'; // apply和options方法和方案一中的保持一致 }
4. 编译前端资源
运行npm run dev或者npm run prod编译组件资源,生效后就能看到联动效果了。
注意事项
- 确保
Product模型的manufacturer和model字段数据干净,没有空值或无效数据,避免分组后出现异常选项。 - 如果你用了软删除,
withoutTrashed()能保证不会包含已删除的产品数据。 - 测试时可以检查Network请求,确认厂商筛选值是否正确传递到后端,以及返回的型号列表是否符合预期。
内容的提问来源于stack exchange,提问作者Murlidhar Fichadia
相关产品推荐
相关产品推荐

