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

如何使用spatie/laravel-query-builder实现带关联关系的数据筛选与搜索?(Laravel框架)

Fixing Your Student Filter & Implementing with spatie/laravel-query-builder

Hey there! Let's start by fixing the core issue in your original code—then we'll refactor it to use spatie/laravel-query-builder for cleaner, more maintainable code.

Why Your Original Query Isn't Working

The problem is with how your orWhere clauses are structured. Right now, your query logic looks like this:

(User has a Student role AND name matches search) OR nisn matches search OR username matches search

That's why non-Student users are showing up—if their nisn or username matches the keyword, they bypass the role check. To fix this, you need to group the three "match keyword" conditions into a single logical block, so the final logic becomes:

User has a Student role AND (name matches OR nisn matches OR username matches)

Fixed Native Laravel Query

Here's how to adjust your original code:

public function searchStudent(Request $request) {
    $user = Auth::user(); // For avatar
    $searchTerm = $request->table_search;

    $filteredStudents = User::whereHas('roles', function($q){
        $q->where('name', 'Student');
    })->where(function($query) use ($searchTerm) {
        // Group these conditions so they're all checked together
        $query->where('name','like',"%{$searchTerm}%")
              ->orWhere('nisn','like',"%{$searchTerm}%")
              ->orWhere('username','like',"%{$searchTerm}%");
    })->get();

    return view('pages.admin.user.student.showStudentFiltered', compact('filteredStudents', 'user') );
}

Implementing with spatie/laravel-query-builder

Now, let's refactor this to use the package for a more scalable solution (great if you ever need to add more filters later).

Step 1: Make Sure the Package is Installed

First, if you haven't already, install the package via Composer:

composer require spatie/laravel-query-builder

Step 2: Refactor the Controller Method

We'll use QueryBuilder to encapsulate our filters, making the code cleaner and adding built-in protection against invalid filter parameters.

use Spatie\QueryBuilder\QueryBuilder;
use Spatie\QueryBuilder\AllowedFilter;

public function searchStudent(Request $request) {
    $user = Auth::user();
    $searchTerm = $request->table_search;

    $filteredStudents = QueryBuilder::for(User::class)
        // Define allowed filters to prevent arbitrary database queries
        ->allowedFilters([
            // Filter to only include users with the Student role
            AllowedFilter::callback('student_role', function ($query) {
                $query->whereHas('roles', fn($q) => $q->where('name', 'Student'));
            }),
            // Multi-field search for name, nisn, username
            AllowedFilter::callback('search', function ($query, $value) {
                $query->where(function($q) use ($value) {
                    $q->where('name', 'like', "%{$value}%")
                      ->orWhere('nisn', 'like', "%{$value}%")
                      ->orWhere('username', 'like', "%{$value}%");
                });
            }),
        ])
        // Apply our fixed filters: enforce Student role + apply search term if present
        ->filter([
            'student_role' => true,
            ...($searchTerm ? ['search' => $searchTerm] : [])
        ])
        ->get();

    return view('pages.admin.user.student.showStudentFiltered', compact('filteredStudents', 'user') );
}

Alternative: Simplify if Student Role is Always Required

If this endpoint will always filter for Student users (no need to toggle it), you can simplify the query by starting with the role filter directly:

$filteredStudents = QueryBuilder::for(User::whereHas('roles', fn($q) => $q->where('name', 'Student')))
    ->allowedFilters([
        AllowedFilter::callback('search', function ($query, $value) {
            $query->where(function($q) use ($value) {
                $q->where('name', 'like', "%{$value}%")
                  ->orWhere('nisn', 'like', "%{$value}%")
                  ->orWhere('username', 'like', "%{$value}%");
            });
        }),
    ])
    ->when($searchTerm, fn($query) => $query->filter(['search' => $searchTerm]))
    ->get();

Key Benefits of Using spatie/laravel-query-builder

  • Maintainability: Add new filters later by just adding to allowedFilters
  • Security: Automatically blocks invalid filter parameters from being applied
  • Readability: Makes complex filtering logic more explicit and easy to follow

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:33:11