PHP+Mysql实现分页
我们在项目开发的过程中避免不了使用分页功能,拿php来说,现在市面上有很多大大小小的php框架,当然了分页这种小功能这些框架中都是拿来直接可以用的。
这些框架的分页功能使用都很方便,配置一下分页所需参数立马就能出结果,对于开发人员来说是非常方便的。但是有些时候就会发现这些分页功能不是自己期望的,
当然拿框架的分页修改一下是可以实现我们的需求的,但是永远局限于框架本身的封装,那么我们怎么样定义自己的分页类呢,那么现在就要求我们不仅要知其然,更要知其所以然,
好了,废话那么多,咱们开始正题。
要实现分页功能,首先要知道数据总条数、每页显示的条数、显示几个分页码,这三个可谓是必要条件。
我们先看一下具体的实现效果
假设表结构是这样
CREATE TABLE `article_information` (
`inf_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`inf_title` varchar(50) NOT NULL DEFAULT '',
`inf_smtitle` varchar(50) NOT NULL DEFAULT '',
`inf_cid` int(10) unsigned NOT NULL,
`inf_hits` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`inf_id`)
) ENGINE=MyISAM AUTO_INCREMENT=210 DEFAULT CHARSET=utf8;
首先我们连接数据库,php代码为:
$host = '127.0.0.1';
$db_user = 'root';
$db_pass = 'root';
$db_name = 'article'; $link = new mysqli($host,$db_user,$db_pass);
if($link->errno){
printf("数据库链接失败:".mysqli_connect_error());
exit();
}
if( ! $link->select_db($db_name)){
printf("数据库选择失败");
exit();
} $count_sql = "SELECT COUNT(1) nums FROM article_information";//查询数据总条数
$query = $link->query($count_sql);
$row_count = $query->fetch_assoc();
$query->free_result();
$total = $row_count['nums'];
$page_size = 10; $cur_page = get_url_param(parse_url($_SERVER['REQUEST_URI'])['path'],4);
//假如url链接为,http://xxx.net/fenye.php/index/list/6?age=20&city=40
//我这边以平常开发常用的url链接为例,我这个链接只有两层index/list,如果是tp的话无路由链接一般为index/index/list(模块/控制器/方法)
get_url_param函数为:
/**
* 获取url中的分段数据
* @param $url 链接url
* @param $seg 获取url中的第几段
*/
function get_url_param($url,$seg){
$url = explode('/',$url);
return isset($url[$seg]) ? $url[$seg] : 1;
}
接着继续,知道了总条数和每页显示的条数以后,下面我们开始取页码范围内的数据
$start = ($cur_page-1)*$page_size;//按照分页规律计算出数据起始条数 $sql = "SELECT inf_id,inf_title FROM py_information LIMIT $start,$page_size";
if ($result = $link->query($sql)){
$arr = [];
while ($row = $result->fetch_assoc()){
$arr[] = $row;
}
}
现在我们已经把数据取出来了,下面我们开始写分页类。
下面是分页类的初始化配置:
具体配置参数我已经注释的很详细了,个别说明一下
$params参数:很多时候我们列表的分页会用到很多的查询参数,我经常看到各个框架论坛里面有同学问怎么把搜索参数带入到分页里面,那么这个参数就是让你把你的筛选参数组合到url中,格式为?id=20&city=30,
下面我们会讲如何将参数组合成这种格式的。
$base_url参数:当前链接(不带参数和页码),例如我们当前访问的地址为:http://xxx.net/fenye.php/index/list/6?age=20&city=40,那么$base_url =/fenye.php/index/list,我这是用原生php写的例子,如果用框架的话相关php文件是可以省略的。
class Mypage{
private $cur_page;//当前页
private $total;//总条数
private $page_size = 10;//每页显示的条数
private $total_page;//总页数
private $first_page;//首页显示名称
private $pre_page;//上一页的显示名称
private $nex_page;//下一页的显示名称
private $end_page;//尾页名称
private $params;//分页后面的筛选参数
private $num_size = 2;//当前页前后显示几个分页码
private $base_url;//分页链接地址
public function __construct(array $page_config=[])
{
$this->cur_page = $page_config['cur_page'];
$this->total = $page_config['total'];
$this->page_size = $page_config['page_size'];
$this->base_url = $page_config['base_url'];
$this->pre_page = isset($page_config['pre_page']) ? $page_config['pre_page'] : "上一页";
$this->nex_page = isset($page_config['next_page']) ? $page_config['next_page'] : "下一页";
$this->end_page = isset($page_config['end_page']) ? $page_config['end_page'] : "尾页";
$this->first_page = isset($page_config['first_page']) ? $page_config['first_page'] : "首页";
$this->num_size = isset($page_config['num_size']) ? $page_config['num_size'] : 2;
$this->params = isset($page_config['params']) ?$page_config['params'] : '';
$this->total_page = ceil($this->total/$this->page_size);
}
}
配置好分页类,那么下一步我们就要获取分页码了,像下面图片中的分页样式一样。
我们来看一下一个分页地址需要哪些东西,假如第5页的链接地址为:
<a href="/fenye.php/index/list/5?age=20&city=40">5</a>
首先我们要组合第5页的链接地址/fenye.php/index/list/5?age=20&city=40,然后再返回<a href="/fenye.php/index/list/5?age=20&city=40">5</a>这个链接,
下面我们来具体实现
获取指定页码的地址:
/**
* 获取分页地址 xxx.com/index/3
* @param $i
*/
public function get_url($i){
return $this->base_url.'/'.$i;
}
返回整体页码链接,上面我们已经说了分页参数问题,这里$url.=$this->params就是对每一页的url后面都带上分页参数,这样就确保参数的正确性:
/**
* 获取分页完整链接
* @param $url
*/
public function get_link($url,$text){
if ($this->params) $url.=$this->params;
return "<a href='$url'>$text</a>";
}
有了上面两个函数,现在我们来获取一下第1页的页码链接,下面做了一个小小的判断,我想大家都能看明白,就是当前不是第一页就返回有链接的地址,否则只返回一个链接名称:
/**
* 获取首页的链接地址
*/
public function get_first_page(){
if ($this->cur_page > 1 && $this->cur_page != 1){
return $this->get_link($this->get_url(1),$this->first_page);
}
return "<span>$this->first_page</span>";
}
和上面类似,我们获取一个其它页码的链接地址:
/**
* 获取上一页链接地址
*/
public function get_prev_page(){
if ($this->cur_page > 1 && $this->cur_page !=1){
return $this->get_link($this->get_url($this->cur_page-1),$this->pre_page);
}
return '<span>'.$this->pre_page.'</span>';
} /**
* 获取下一页链接地址
* @return string
*/
public function get_next_page(){
if ($this->cur_page < $this->total_page){
return $this->get_link($this->get_url($this->cur_page+1),$this->nex_page);
}
return '<span>'.$this->nex_page.'</span>';
} /**
* 获取...符号
* @return string
*/
public function get_ext(){
return '<span>...</span>';
} /**
* 获取尾页地址
*/
public function get_end_page(){
if ($this->cur_page < $this->total_page){
return $this->get_link($this->get_url($this->total_page),$this->end_page);
}
return '<span>'.$this->end_page.'</span>';
}
还差一点,就是中间的数字页码,注释我已经写得很清楚了:
/**
* 中间的数字分页
*/
public function now_bar(){
if ($this->cur_page > $this->num_size){
$begin = $this->cur_page - $this->num_size;
$end = $this->cur_page + $this->num_size;
//判断最后一页是否大于总页数
if ($end > $this->total_page){
//重新计算开始页和结束页
$begin = ($this->total_page - 2*$this->num_size > 0) ? $this->total_page - 2*$this->num_size : 1;
//这里为什么用2*$this->num_size呢?因为当前页前后有2个$this->num_size的间距,所以这里是2*$this->num_size
$end = $this->total_page;
}
}else{
$begin = 1;
$end = 2*$this->num_size+1;//此处的2和上面已经解释过了,+1是因为除了当前页,前后还有2*$this->num_size的间距,所以总页码条数为2*$this->num_size+1
}
$page_html='';
for ($i=$begin;$i<=$end;$i++){
if ($i == $this->cur_page){
$page_html .= '<span class="disabled">'.$i.'</span>';
}else{
$page_html .= $this->get_link($this->get_url($i),$i);
}
}
return $page_html;
}
其它的两个函数
/**
* 返回总条数
* @return string
*/
public function show_total_row(){
return "共{$this->total}条";
} /**
* 返回总页数
*/
public function show_total_page(){
return "共{$this->total_page}页";
}
最后输出分页:
/**
* 输出分页码
*/
public function show_page(){
$show_page = '';
$ext = ($this->cur_page>$this->num_size) ? $this->get_ext() : '';
$show_page.= $this->show_total_row();
$show_page.= $this->show_total_page();
$show_page.= $this->get_first_page();
$show_page.= $this->get_prev_page();
$show_page.= $ext;
$show_page.= $this->now_bar();
$show_page.= $ext;
$show_page.= $this->get_next_page();
$show_page.= $this->get_end_page(); return $show_page;
}
以上就是分页的实现原理,下面我会给出具体代码,上面我们说过我们的查询参数组装成?id=20&city=30这种格式的来拼接到url后面,下面我们来看一下具体实现过程。
例如我们把分页条件都放进一个数组中:
$condition = [
'age'=>20,
'city'=>40
];
下面我们来进行url组合:
/**
* 组合url参数 ?id=2&city=3
* @param array $data
*/
function make_url(array $data=[]){
$link = '?';
$suffix = '&';
foreach ($data as $key=>$val){
$link .= $key.'='.$val.$suffix;
}
return trim($link,$suffix);
}
ok参数已经组合成我们所希望的格式了,其实就是一个foreach拼装数据的过程。
以上是一个原理和逻辑,下面给出所有代码:
完整分页类:
<?php
/**
* Created by PhpStorm.
* User: 123456
* Date: 2018/9/4
* Time: 17:24
*/
class Mypage{
private $cur_page;//当前页
private $total;//总条数
private $page_size = 10;//每页显示的条数
private $total_page;//总页数
private $first_page;//首页显示名称
private $pre_page;//上一页的显示名称
private $nex_page;//下一页的显示名称
private $end_page;//尾页名称
private $params;//分页后面的筛选参数
private $num_size = 2;//当前页前后显示几个分页码
private $base_url;//分页链接地址
public function __construct(array $page_config=[])
{
$this->cur_page = $page_config['cur_page'];
$this->total = $page_config['total'];
$this->page_size = $page_config['page_size'];
$this->base_url = $page_config['base_url'];
$this->pre_page = isset($page_config['pre_page']) ? $page_config['pre_page'] : "上一页";
$this->nex_page = isset($page_config['next_page']) ? $page_config['next_page'] : "下一页";
$this->end_page = isset($page_config['end_page']) ? $page_config['end_page'] : "尾页";
$this->first_page = isset($page_config['first_page']) ? $page_config['first_page'] : "首页";
$this->num_size = isset($page_config['num_size']) ? $page_config['num_size'] : 2;
$this->params = isset($page_config['params']) ?$page_config['params'] : '';
$this->total_page = ceil($this->total/$this->page_size);
} /**
* 获取首页的链接地址
*/
public function get_first_page(){
if ($this->cur_page > 1 && $this->cur_page != 1){
return $this->get_link($this->get_url(1),$this->first_page);
}
return "<span>$this->first_page</span>";
} /**
* 获取上一页链接地址
*/
public function get_prev_page(){
if ($this->cur_page > 1 && $this->cur_page !=1){
return $this->get_link($this->get_url($this->cur_page-1),$this->pre_page);
}
return '<span>'.$this->pre_page.'</span>';
} /**
* 获取下一页链接地址
* @return string
*/
public function get_next_page(){
if ($this->cur_page < $this->total_page){
return $this->get_link($this->get_url($this->cur_page+1),$this->nex_page);
}
return '<span>'.$this->nex_page.'</span>';
} /**
* 获取...符号
* @return string
*/
public function get_ext(){
return '<span>...</span>';
} /**
* 获取尾页地址
*/
public function get_end_page(){
if ($this->cur_page < $this->total_page){
return $this->get_link($this->get_url($this->total_page),$this->end_page);
}
return '<span>'.$this->end_page.'</span>';
} /**
* 中间的数字分页
*/
public function now_bar(){
if ($this->cur_page > $this->num_size){
$begin = $this->cur_page - $this->num_size;
$end = $this->cur_page + $this->num_size;
//判断最后一页是否大于总页数
if ($end > $this->total_page){
//重新计算开始页和结束页
$begin = ($this->total_page - 2*$this->num_size > 0) ? $this->total_page - 2*$this->num_size : 1;
//这里为什么用2*$this->num_size呢?因为当前页前后有2个$this->num_size的间距,所以这里是2*$this->num_size
$end = $this->total_page;
}
}else{
$begin = 1;
$end = 2*$this->num_size+1;//此处的2和上面已经解释过了,+1是因为除了当前页,前后还有2*$this->num_size的间距,所以总页码条数为2*$this->num_size+1
}
$page_html='';
for ($i=$begin;$i<=$end;$i++){
if ($i == $this->cur_page){
$page_html .= '<span class="disabled">'.$i.'</span>';
}else{
$page_html .= $this->get_link($this->get_url($i),$i);
}
}
return $page_html;
} /**
* 输出分页码
*/
public function show_page(){
$show_page = '';
$ext = ($this->cur_page>$this->num_size) ? $this->get_ext() : '';
$show_page.= $this->show_total_row();
$show_page.= $this->show_total_page();
$show_page.= $this->get_first_page();
$show_page.= $this->get_prev_page();
$show_page.= $ext;
$show_page.= $this->now_bar();
$show_page.= $ext;
$show_page.= $this->get_next_page();
$show_page.= $this->get_end_page(); return $show_page;
} /**
* 获取分页地址 xxx.com/index/3
* @param $i
*/
public function get_url($i){
return $this->base_url.'/'.$i;
} /**
* 获取分页完整链接
* @param $url
*/
public function get_link($url,$text){
if ($this->params) $url.=$this->params;
return "<a href='$url'>$text</a>";
} /**
* 返回总条数
* @return string
*/
public function show_total_row(){
return "共{$this->total}条";
} /**
* 返回总页数
*/
public function show_total_page(){
return "共{$this->total_page}页";
}
}
前台页面:
<?php
include_once ('Mypage.php');
$host = '127.0.0.1';
$db_user = 'root';
$db_pass = 'root';
$db_name = 'article';
$link = new mysqli($host,$db_user,$db_pass); if (mysqli_connect_errno()){
printf("数据库链接失败了:".mysqli_connect_error());
exit();
}
if ( ! $link->select_db($db_name)){
printf("你选择的数据库{$db_name}不存在");
exit();
} $page_size = 10;
//p($url);
//p(__DIR__);
//p(__FILE__);
//p(pathinfo(__FILE__, PATHINFO_BASENAME)); $condition = [
'age'=>20,
'city'=>40
]; //p(make_url($condition)); //$cur_page = isset($_GET['page']) ? $_GET['page'] : 1;
$cur_page = get_url_param(parse_url($_SERVER['REQUEST_URI'])['path'],4);
//假如url链接为,http://xxx.net/fenye.php/index/list/6?age=20&city=40
//我这边以平常开发常用的url链接为例,我这个链接只有两层index/list,如果是tp的话无路由链接一般为index/index/list(模块/控制器/方法) $sql = "SELECT COUNT(1) nums FROM py_information";
$query = $link->query($sql);
$row = $query->fetch_assoc();
$total = $row['nums'];//数据总条数 $page_config=[
'cur_page'=>$cur_page,
'total'=>$total,
'page_size'=>$page_size,
'base_url'=>'/fenye.php/index/list',
'num_link'=>2,
'params'=>make_url($condition)
]; $mypage = new Mypage($page_config); $start = ($cur_page-1)*$page_size;//按照分页规律计算出数据起始条数 $sql = "SELECT inf_id,inf_title FROM article LIMIT $start,$page_size";
if ($result = $link->query($sql)){
$arr = [];
while ($row = $result->fetch_assoc()){
$arr[] = $row;
}
} /**
* 获取url中的分段数据
* @param $url 链接url
* @param $seg 获取url中的第几段
*/
function get_url_param($url,$seg){
$url = explode('/',$url);
return isset($url[$seg]) ? $url[$seg] : 1;
} /**
* 组合url参数 ?id=2&city=3
* @param array $data
*/
function make_url(array $data=[]){
$link = '?';
$suffix = '&';
foreach ($data as $key=>$val){
$link .= $key.'='.$val.$suffix;
}
return trim($link,$suffix);
} function p($data){
echo '<pre>';
print_r($data);
echo '</pre>';
};
?> <html lang="en"> <head>
<meta charset="utf-8">
<title>充值</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<style type="text/css"> .page_nav { font-family: Simsun; line-height:normal;text-align: right;margin-top: 10px;overflow: hidden;zoom: 1;text-align:center}
.page_nav a,.page_nav span,.page_nav input{display:inline-block;line-height:23px;padding:0 10px;border:1px solid #ccc;background-color:#fff; text-decoration:none;color:#666;margin-right:5px;zoom: 1;}
.page_nav input{height: 23px;line-height: 23px;padding: 0;zoom: 1; font:12px/16px;font-family: Simsun;zoom: 1;_margin-bottom:-4px;}
.page_nav a:hover,.page_nav span.pg_curr{color:#fff !important;background-color:#C00;border-color:#be0d11 #be0d11 #9a0307; text-decoration:none;}
.disabled{ background: #C00 !important; color: #fff !important;}
</style>
</head> <body> <table>
<thead>
<th>id</th>
<th>标题</th>
</thead>
<?php foreach($arr as $key=>$val):?>
<tr>
<td><?php echo $val['inf_id'];?></td>
<td><?php echo $val['inf_title'];?></td>
</tr>
<?php endforeach;?>
</table>
<div class="page_nav" style="margin: 15px;">
<?=$mypage->show_page();?>
</div> </body>
</html>
你可以将此分页类移植到tp或者CI等其它框架中去。
数据库你可以随便找一个,这里我就不提供了,感谢大家的阅读,有不对的地方请指正。
另外我在github上面开源了一些项目,觉得有用的给个star,地址:https://github.com/sunjiaqiang
PHP+Mysql实现分页的更多相关文章
- MySQL的分页优化
今天下午,帮同事重写了一个MySQL SQL语句,该SQL语句涉及两张表,其中一张表是字典表(需返回一个字段),另一张表是业务表(本身就有150个字段,需全部返回),当然,字段的个数是否合理在这里不予 ...
- oracle sqlserver mysql数据库分页
1.Mysql的limit用法 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能. SELECT * FROM tabl ...
- MySQL的分页
有朋友问: MySQL的分页似乎一直是个问题,有什么优化方法吗?网上看到网上推荐了一些分页方法,但似乎不太可行,你能点评一下吗? 方法1: 直接使用数据库提供的SQL语句 ---语句样式: MySQL ...
- MySql通用分页存储过程
MySql通用分页存储过程 1MySql通用分页存储过程 2 3过程参数 4p_cloumns varchar(500),p_tables varchar(100),p_where varchar(4 ...
- Statement和PreparedStatement的特点 MySQL数据库分页 存取大对象 批处理 获取数据库主键值
1 Statement和PreparedStatement的特点 a)对于创建和删除表或数据库,我们可以使用executeUpdate(),该方法返回0,表示未影向表中任何记录 b)对于创建和 ...
- mysql 查询优化~ 分页优化讲解
一 简介:今天咱们来聊聊mysql的分页查询二 语法 LIMIT [offset,] rows offset是第多少条 rows代表多少条之后的行数 性能消耗 se ...
- mysql实现分页的几种方式
mysql实现分页的几种方式: 第一种:使用框架自带的pageable来进行分页 package com.cellstrain.icell.repository.repositoryImpl; imp ...
- mybatis对mysql进行分页
Mybatis对mysql数据库分页 在generator中增加插件,下载地址http://download.csdn.net/detail/shunlongjin/6937045 <plugi ...
- atitit。mssql sql server 转换mysql 及 分页sql ast的搭建
atitit.mssql sql server 转换mysql 及 分页sql ast的搭建 1. 主要的的转换::函数的转换,分页的转换 1 2. 思路::mssql sql >>as ...
- oracle 的分页与 mySQL'的分页转化
oracle 分页: 关键字ROWNUM SELECT EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO FROM ( SELECT A.*, ...
随机推荐
- 上传到git
https://blog.csdn.net/Lucky_LXG/article/details/77849212
- eclipse添加tomcat运行环境
- day03 内部类
- Codeforces 1139D(推式子+dp)
题目传送 推公式博客传送 推完式子就是去朴素地求就行了Orz const int maxn = 1e5 + 5; const int mod = 1e9 + 7; int m, mu[maxn], v ...
- 最长上升子序列LIS(云笔记图片版)
- python_12(并发编程)
第1章 进程 1.1 队列Queue 1.2 Queue方法 1.2.1 q.get([block [,timeout]]) 1.2.2 q.get_nowait() 1.2.3 q.put(item ...
- wordpress注册收不到邮件
解决发送问题后又遇到个蛋疼的问题,点击激活邮件地址提示您的密码重设链接无效,请在下方请求新链接发现原来是显的没事的wordpress在激活链接前后都加了<>,而邮箱把后面的>当成是链 ...
- bootstrap-table 基础用法
1.需要添加的引用. <script src="@Url.Content("~/js/jquery-2.1.1.js")"></script& ...
- deepin15.2无线网无法使用
原文链接:https://bbs.deepin.org/forum.php?mod=viewthread&tid=40276&highlight=%E6%97%A0%E7%BA%BF% ...
- CF747D Winter Is Coming
题目链接: http://codeforces.com/problemset/problem/747/D 题目大意: 接下来的n天内每天都有一个气温,如果某天的温度为负数,则必须使用冬季轮胎:而温度 ...