php分页必须校验并转换$_get['page']为整数,用filter_input或(int)强转;限制页码范围防sql性能问题;保留所有get参数生成链接;必须带确定性order by避免数据错乱。

$_GET['page']必须转成整数再比较
PHP里$_GET['page']是字符串,直接用if ($_GET['page'] > 1)会按字典序比,导致'10' > '2'为false。结果“上一页”按钮在第10页就消失了。
实操建议:
- 用
(int)$_GET['page']强转,或更安全的filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, ['options' => ['default' => 1, 'min_range' => 1]]) - 校验失败时返回
false,必须检查:如果$page === false,就重定向到page=1或抛出400错误 - 别用
is_numeric()——它会放行'1e5'这种科学计数法字符串,可能绕过范围限制
页码必须落在合法区间内
用户手动改URL,比如输?page=9999999,不拦截就会让MySQL执行LIMIT 9999990, 10,扫描近千万行后丢弃,超时或OOM。
实操建议:
- 算出最大页码:
$total_pages = ceil($total_count / $per_page),然后取$page = min($page, $total_pages) - 更保守的做法是硬性限制上限,比如
$page = min($page, 200),防止恶意翻页拖垮数据库 - 对管理后台等敏感接口,额外加权限校验——不能只靠“隐藏链接”,得在查数据前确认当前用户是否有权访问该页
生成下一页链接时要保留所有过滤参数
点“下一页”后搜索条件丢了,是因为只拼了page,没带上q=xxx、category=2这些。结果第二页查的是全量数据,和第一页对不上。
实操建议:
- 用
http_build_query(array_merge($_GET, ['page' => $next_page]))构造URL,自动合并现有参数 - 排除不需要透传的键,比如
unset($params['sort'])再拼,避免把临时排序参数带到下一页 - 如果用POST提交筛选条件,分页必须改用
session或隐藏字段存状态,不能依赖GET
ORDER BY缺失会导致翻页错乱
没写ORDER BY的分页查询,MySQL每次返回顺序可能不同。同一条记录在第1页和第2页重复出现,或者直接消失——这不是Bug,是SQL标准行为。
实操建议:
- 所有分页
SELECT必须带确定性ORDER BY,首选主键(ORDER BY id ASC)或唯一时间戳(ORDER BY created_at DESC, id DESC) - 禁用
ORDER BY RAND()和非唯一字段(如status),否则LIMIT OFFSET语义失效 - 如果业务真要按热度排序,得先固化值(加
hot_score列并定时更新),不能实时计算后排序
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











