
本文介绍如何在 Laravel Nova 中实现两个 Select Filter 的级联联动,使“型号”筛选器能根据所选“制造商”动态更新可选项,解决多级依赖筛选场景下的用户体验与数据准确性问题。
本文介绍如何在 Laravel Nova 中实现两个 Select Filter 的级联联动,使“型号”筛选器能根据所选“制造商”动态更新可选项,解决多级依赖筛选场景下的用户体验与数据准确性问题。
在 Laravel Nova 中,默认的 Filter 类不支持跨过滤器状态通信,因此无法直接在 Model 过滤器的 options() 方法中读取 Manufacturer 过滤器当前选中的值——这也是原问题中 $request->input() 或尝试解码请求参数返回 null 的根本原因。官方 Nova 并未内置依赖式(Dependent)筛选逻辑,需借助社区扩展方案实现。
推荐使用开源库 awesome-nova/dependent-filter,它专为 Nova 设计,通过轻量级 Vue 组件 + 后端钩子,实现了过滤器间的响应式联动,无需修改 Nova 核心,兼容性好且易于集成。
✅ 安装与配置
首先通过 Composer 安装依赖:
composer require awesome-nova/dependent-filter
发布前端资源(如使用 Nova v4+ 且启用 --no-publish 模式,请确认已运行 php artisan nova:publish --force):
php artisan vendor:publish --provider="AwesomeNova\Providers\DependentFilterServiceProvider"
✅ 改造 Manufacturer 过滤器(父级)
继承 AwesomeNova\Filters\DependentFilter 替代原生 Filter,并定义唯一 attribute(作为依赖键名):
<?php
namespace App\Nova\Filters;
use Illuminate\Http\Request;
use App\Models\Product;
use AwesomeNova\Filters\DependentFilter;
class Manufacturer extends DependentFilter
{
public $name = '制造商';
public $attribute = 'manufacturer'; // ← 关键:此 key 将被 Model 过滤器引用
public $component = 'awesome-nova-dependent-filter';
public function apply(Request $request, $query, $value)
{
return $query->whereHas('product', fn ($q) => $q->where('manufacturer', $value));
}
public function options(Request $request, array $filters = [])
{
return Product::select('manufacturer')
->distinct()
->orderBy('manufacturer')
->pluck('manufacturer')
->mapWithKeys(fn ($m) => [$m => $m])
->toArray();
}
}? 注意:options() 方法签名已增强为 options(Request $request, array $filters = []),虽本例未使用 $filters,但该参数是子过滤器获取父值的基础通道。
✅ 改造 Model 过滤器(子级,依赖 Manufacturer)
关键在于声明 public $dependentOf = ['manufacturer'],并利用 $filters['manufacturer'] 动态构建查询:
<?php
namespace App\Nova\Filters;
use Illuminate\Http\Request;
use App\Models\Product;
use AwesomeNova\Filters\DependentFilter;
class Model extends DependentFilter
{
public $name = '型号';
public $attribute = 'model';
public $component = 'awesome-nova-dependent-filter';
public $dependentOf = ['manufacturer']; // ← 声明依赖关系
public $hideWhenEmpty = true; // 当 manufacturer 未选时,自动隐藏本过滤器(可选)
public function apply(Request $request, $query, $value)
{
return $query->whereHas('product', fn ($q) => $q->where('model', $value));
}
public function options(Request $request, array $filters = [])
{
// ✅ 此处 $filters['manufacturer'] 即前端选中的值(已由 JS 自动注入)
$manufacturer = $filters['manufacturer'] ?? null;
if (! $manufacturer) {
return []; // 无制造商时返回空选项,配合 $hideWhenEmpty 更友好
}
return Product::select('model')
->where('manufacturer', $manufacturer)
->distinct()
->orderBy('model')
->pluck('model')
->mapWithKeys(fn ($m) => [$m => $m])
->toArray();
}
}✅ 在 Resource 中注册(注意使用 ::make())
// app/Nova/Review.php
public function filters(Request $request)
{
return [
Manufacturer::make(), // 必须调用 make() 以启用依赖注入
Model::make(),
];
}⚠️ 注意事项与最佳实践
-
字段一致性:确保
dependentOf数组中的键(如'manufacturer')与父过滤器的$attribute完全一致(大小写、下划线等),否则依赖无法识别; -
数据库性能:若
Product表数据量大,建议为(manufacturer, model)字段添加联合索引:ALTER TABLE products ADD INDEX idx_manufacturer_model (manufacturer, model);
-
空值处理:子过滤器
options()中务必检查$filters[$key]是否存在,避免 SQL 错误;$hideWhenEmpty = true可提升 UI 清洁度; -
多级依赖:
$dependentOf支持数组,例如['category', 'brand'],options()中可同时使用$filters['category']和$filters['brand']构建复合查询; -
缓存优化(进阶):对高频访问的选项列表,可在
options()中加入 Laravel 缓存层,例如Cache::remember("models_{$manufacturer}", 3600, fn () => ...)。
通过以上改造,用户在 Nova 后台选择“Apple”后,“型号”下拉框将实时仅显示 Apple 相关机型(如 iPhone 15、MacBook Pro 等),显著提升筛选效率与数据准确性,真正实现企业级管理后台所需的智能过滤体验。



















