侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1824 篇文章
  • 累计收到 0 条评论

在Laravel中如何实现一个支持分页、搜索和排序的用户列表API?

2025-12-12 / 0 评论 / 4 阅读

题目

在Laravel中如何实现一个支持分页、搜索和排序的用户列表API?

信息

  • 类型:问答
  • 难度:⭐⭐

考点

Eloquent查询构建,请求参数验证,分页器处理,API资源转换

快速回答

实现步骤:

  1. 通过请求对象获取查询参数(页码、搜索关键词、排序字段)
  2. 使用Eloquent的when()条件查询处理搜索和排序
  3. 调用paginate()方法实现分页
  4. 使用API资源类格式化响应结构

关键代码:

$users = User::query()
    ->when($request->search, fn($q) => $q->where('name','like',"%{$request->search}%"))
    ->orderBy($request->sort_by ?? 'id', $request->sort_dir ?? 'asc')
    ->paginate($request->per_page ?? 15);

return UserResource::collection($users);
## 解析

该功能考察Laravel核心组件的综合应用能力,下面分步骤说明实现细节:

1. 请求参数处理与验证

// 在控制器方法中注入请求对象
public function index(Request $request)
{
    // 验证参数(Laravel内置验证器)
    $validated = $request->validate([
        'page' => 'sometimes|integer|min:1',
        'per_page' => 'sometimes|integer|min:1|max:100',
        'search' => 'sometimes|string|max:50',
        'sort_by' => 'sometimes|in:name,email,created_at',
        'sort_dir' => 'sometimes|in:asc,desc'
    ]);
    // ...后续逻辑
}

原理说明:使用Laravel的FormRequest或直接validate()方法确保输入安全,防止SQL注入和无效参数。

2. 构建动态查询

$query = User::query();

// 搜索处理(多字段示例)
if ($request->has('search')) {
    $search = $request->search;
    $query->where(function ($q) use ($search) {
        $q->where('name', 'like', "%$search%")
          ->orWhere('email', 'like', "%$search%");
    });
}

// 排序处理(防止注入)
$sortBy = in_array($request->sort_by, ['name','email']) 
          ? $request->sort_by 
          : 'created_at';
$sortDir = $request->sort_dir === 'desc' ? 'desc' : 'asc';
$query->orderBy($sortBy, $sortDir);

最佳实践

  • 使用when()方法使条件查询更流畅
  • 对排序字段进行白名单校验
  • 搜索使用闭包避免orWhere链断裂

3. 分页与响应格式化

// 分页处理
$perPage = $request->per_page ?? config('app.default_per_page');
$users = $query->paginate($perPage);

// 使用API资源类(UserResource.php)
class UserResource extends JsonResource {
    public function toArray($request) {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at->toIso8601String()
        ];
    }
}

// 控制器返回
return UserResource::collection($users);

响应结构示例

{
    "data": [
        {"id":1, "name":"John", ...}
    ],
    "meta": {
        "current_page": 1,
        "per_page": 15,
        "total": 100
    }
}

4. 常见错误与优化

  • N+1查询问题:在查询中使用->with('posts')预加载关联数据
  • 性能问题:对搜索字段添加数据库索引,大数据量时考虑Elasticsearch
  • 安全漏洞:永远不要直接将请求参数传入orderBy(),必须校验字段合法性
  • 分页参数:限制每页最大数量防止DoS攻击

5. 扩展知识

  • API资源集合:可创建UserResourceCollection自定义分页元数据结构
  • 更复杂的搜索:使用Laravel Scout实现全文搜索
  • 缓存策略:对高频查询添加Redis缓存:->remember(now()->addMinutes(30))
  • 测试技巧:使用Laravel HTTP测试模拟分页请求:$response->assertJsonStructure(['data','meta'])