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

如何在Laravel中实现跨多视图持久化的全局过滤器?

Laravel全局筛选栏跨页面保持状态的实现方案

下面是几种高效且实用的实现方式,你可以根据需求选择:

1. Session存储筛选状态(最常用)

直接把筛选参数存入Session,所有需要应用筛选的页面从Session读取参数,状态在用户会话内持续有效。

实现步骤:

  • 提交筛选时存储参数:在处理筛选提交的控制器方法中,将请求参数存入Session:
    public function applyFilters(Request $request)
    {
        // 先验证参数合法性
        $validated = $request->validate([
            'month' => 'nullable|integer|between:1,12',
            'status' => 'nullable|in:completed,pending,canceled'
        ]);
    
        // 存入Session,可指定过期时间
        session()->put('trade_filters', $validated, now()->addDay());
    
        return redirect()->back();
    }
    
  • 查询时应用筛选:在交易、报表的控制器查询逻辑中,从Session取出参数并应用:
    public function index()
    {
        $filters = session()->get('trade_filters', []);
    
        $trades = Trade::query()
            ->when(isset($filters['month']), function ($query) use ($filters) {
                $query->whereMonth('created_at', $filters['month']);
            })
            ->when(isset($filters['status']), function ($query) use ($filters) {
                $query->where('status', $filters['status']);
            })
            ->get();
    
        return view('trades.index', compact('trades'));
    }
    
  • 清除筛选:添加清除按钮,触发方法删除Session中的筛选参数:
    public function clearFilters()
    {
        session()->forget('trade_filters');
        return redirect()->back();
    }
    
  • 表单回显:在全局筛选栏的表单中,默认填充当前Session的筛选值:
    <input type="number" name="month" min="1" max="12" 
           value="{{ session('trade_filters.month') }}">
    
    <select name="status">
        <option value="">全部状态</option>
        <option value="completed" {{ session('trade_filters.status') == 'completed' ? 'selected' : '' }}>已完成</option>
        <option value="pending" {{ session('trade_filters.status') == 'pending' ? 'selected' : '' }}>待处理</option>
    </select>
    

2. URL查询参数持久化(支持状态分享)

将筛选参数附加到所有相关导航链接中,跳转时参数随URL传递,优点是状态可通过URL分享给他人。

实现步骤:

  • 生成带筛选参数的链接:创建全局辅助函数(在app/helpers.php中),自动拼接当前筛选参数到路由:
    if (!function_exists('route_with_filters')) {
        function route_with_filters(string $name, array $params = []): string
        {
            // 获取当前请求中的筛选参数
            $filters = request()->only(['month', 'status']);
            // 合并路由参数与筛选参数
            return route($name, array_merge($params, $filters));
        }
    }
    
  • 视图中使用辅助函数:所有相关导航链接改用这个辅助函数生成:
    <a href="{{ route_with_filters('trades.index') }}">交易列表</a>
    <a href="{{ route_with_filters('reports.index') }}">交易报表</a>
    
  • 控制器读取参数:直接从请求中获取参数应用筛选:
    public function index(Request $request)
    {
        $month = $request->get('month');
        $status = $request->get('status');
    
        $reports = Report::query()
            ->when($month, fn($q) => $q->whereMonth('trade_date', $month))
            ->when($status, fn($q) => $q->where('trade_status', $status))
            ->get();
    
        return view('reports.index', compact('reports'));
    }
    

3. 混合方案(兼顾持久化与可分享性)

优先读取URL参数,若没有则从Session获取,同时将有效参数同步到Session,兼顾两种方案的优点。

核心逻辑示例:

public function index(Request $request)
{
    // 优先取URL参数,无则取Session
    $month = $request->get('month', session('trade_filters.month'));
    $status = $request->get('status', session('trade_filters.status'));

    // 若有有效参数,同步更新Session
    $validated = [];
    if ($month) $validated['month'] = $month;
    if ($status) $validated['status'] = $status;
    if (!empty($validated)) {
        session()->put('trade_filters', $validated);
    }

    // 应用筛选查询
    $data = Trade::query()
        ->when($month, fn($q) => $q->whereMonth('created_at', $month))
        ->when($status, fn($q) => $q->where('status', $status))
        ->get();

    return view('trades.index', compact('data'));
}

4. 全局中间件自动应用筛选(减少重复代码)

编写全局中间件,自动为指定模型添加查询范围,无需在每个控制器重复编写筛选逻辑。

实现步骤:

  • 创建中间件:
    php artisan make:middleware ApplyTradeFilters
    
  • 编写中间件逻辑:
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    use App\Models\Trade;
    
    class ApplyTradeFilters
    {
        public function handle(Request $request, Closure $next)
        {
            $filters = $request->only(['month', 'status']) ?: session('trade_filters', []);
    
            if (!empty($filters)) {
                // 为Trade模型添加全局查询范围
                Trade::addGlobalScope('trade_filters', function ($query) use ($filters) {
                    $query->when(isset($filters['month']), fn($q) => $q->whereMonth('created_at', $filters['month']));
                    $query->when(isset($filters['status']), fn($q) => $q->where('status', $filters['status']));
                });
    
                // 同步更新Session
                session()->put('trade_filters', $filters);
            }
    
            return $next($request);
        }
    }
    
  • 注册中间件:在app/Http/Kernel.php的$middlewareGroups中,将中间件添加到web组或专门的交易路由组:
    protected $middlewareGroups = [
        'web' => [
            // ...其他中间件
            \App\Http\Middleware\ApplyTradeFilters::class,
        ],
    ];
    
  • 控制器简化查询:此时控制器中无需手动添加筛选逻辑,直接查询即可:
    public function index()
    {
        // 自动应用筛选条件
        $trades = Trade::get();
        return view('trades.index', compact('trades'));
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:01:19