题目
ThinkPHP中如何实现一个带分页和条件查询的用户列表功能?
信息
- 类型:问答
- 难度:⭐⭐
考点
模型操作,查询构造器,分页功能,模板渲染
快速回答
实现带分页和条件查询的用户列表需要以下步骤:
- 使用
where链式方法构建动态查询条件 - 通过
paginate方法实现分页查询 - 在控制器中处理查询参数并传递到视图
- 在模板中使用分页渲染标签和条件参数回填
- 使用
input函数过滤输入保证安全性
核心实现原理
ThinkPHP通过查询构造器(Query Builder)实现安全的数据库操作,结合paginate方法可自动处理分页逻辑:
- 查询构造器:使用链式调用构建SQL,自动过滤危险字符
- 分页机制:
paginate自动计算总记录数、当前页数据及分页HTML - 模板渲染:通过
{$page->render()}输出分页导航
代码实现示例
控制器(UserController.php):
public function index()
{
// 安全获取查询参数
$name = input('get.name/s', '');
$status = input('get.status/d', -1);
// 构建查询条件
$query = UserModel::where('delete_time', null);
if (!empty($name)) {
$query->where('name', 'like', "%{$name}%");
}
if ($status >= 0) {
$query->where('status', $status);
}
// 分页查询(每页10条)
$list = $query->paginate(10, false, [
'query' => request()->param() // 保留URL参数
]);
$this->assign([
'list' => $list,
'name' => $name,
'status' => $status
]);
return $this->fetch();
}模板(index.html):
<form method="get">
<input type="text" name="name" value="{$name}" placeholder="用户名">
<select name="status">
<option value="-1">全部状态</option>
<option value="1" {eq name="status" value="1"}selected{/eq}>启用</option>
<option value="0" {eq name="status" value="0"}selected{/eq}>禁用</option>
</select>
<button type="submit">搜索</button>
</form>
<table>
<!-- 数据列表循环 -->
{volist name="list" id="user"}
<tr>
<td>{$user.name}</td>
<td>{$user.email}</td>
</tr>
{/volist}
</table>
<!-- 分页导航 -->
<div class="page">{$list|raw}</div>最佳实践
- 输入过滤:始终使用
input()函数获取参数,通过类型声明(如/s字符串、/d整数)过滤非法字符 - 条件构建:使用链式查询避免SQL注入,空值判断防止无效条件
- 分页优化:
paginate()的第三个参数传递'query' => request()->param()保留搜索条件 - 模板安全:使用
{$var}自动转义输出,分页变量用|raw过滤防止二次转义
常见错误
- SQL注入风险:直接拼接
"%".$_GET['name']."%"而未使用查询构造器 - 分页参数丢失:未传递
'query'参数导致翻页后搜索条件失效 - N+1查询问题:在循环中关联查询导致性能下降,应使用
with()预加载 - 未处理空值:如
where('status', $status)当$status为空时导致SQL错误
扩展知识
- 关联模型分页:
$list = UserModel::with('profile')->paginate(10); - 自定义分页模板:在
config/paginate.php配置:'var_page' => 'page', // 分页参数名 'type' => 'bootstrap', // 使用Bootstrap样式 'path' => '' // URL路径规则 - 高性能分页:大数据量表使用
paginate()->toArray()配合前端分页库 - API分页:返回JSON格式数据:
return json([ 'list' => $list->gt;return json([ 'list' => $list->items(), 'total' => $list->total() ]);