一. 思路整理
实现一个数据分页功能,需要有数据的总条数,每页展示的条数,和当前在第几页这三个参数
通过⌈总条数/每页展示的条数⌉可以得到总页数,比如某留言板有101条留言,每页展示10条,一那就需要11个页面进行展示
数据分页核心就是通过SQL的limit函数来实现的:用当(前页数-1)*每页显示条数+1就可以得到limit的第一个参数,limit的第二个参数就是当前页显示的数据条数.
还是那个留言板,每页显示10条留言,第三页起始序号为(3-1)*10+1=21,共显示10条,就是limit 21,10 ,也就是从21~30条
二. 3个必要参数
当前页$page使用get方式在url中传入,修改page属性就可以跳转页面,点击上一页下一页等操作都是通过修改page实现的
每页展示条数$listRow在实例化page类时传参的方式定义,通过修改l$istrow就可以设置每页显示的信息条数:
显示的总条数$total通过查询数据库获得:
创建一个数据表messageboard,为了方便只设置id title两个字段
创建数据库连接
$pdoObj = new PDO("mysql:host=localhost;dbname=zhangkwebsite", 'root', 'root');
$pdoObj->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
获取数据的总条数$ncount
$query=$pdoObj->query("select count(*) from messageboard");
$val=$query->fetch(PDO::FETCH_ASSOC);
$ncount=$val['count(*)'];
三. 数据分页类
创建一个数据分页类page,在类中定义好需要使用的变量
class page{ private $total;//总记录数 private $listRows;//每页显示行数 private $limit;//sql语句的limit限制 private $uri;//去掉page属性的uri private $pageNum;//总页数 private $listNum;//页码数量
总记录数和每页显示的条数在用户实例化类时设置
public function __construct($total,$listRows=10){ $this->total=$total; $this->listRows=$listRows;
当前页显示的记录$limit
limit (前页数-1)*每页显示条数+1,每页总条数 和前面的例子完全相同
private function setLimit() { return 'Limit' .' '.($this->page - 1) * $this->listRows .','."{$this->listRows}"; }
setLimit()的返回值将保存在私有变量$limit中,使用__get函数为用户提供一个调用的接口
function __get($args) { if ($args=="limit"){ return $this->limit; } else return null; }
这个字符串在用户查询时拼接在sql语句中
$p=new page($ncount,5);
$query=$pdoObj->query("select * from messageboard {$p->limit}");
获取当前页的第一条和最后一条,这个没什么难度
private function start(){ if($this->total==0) return 0; else return ($this->page - 1) * $this->listRows+1; } private function end(){ return min($this->total,$this->page*$this->listRows); }
pagegetUri()方法:去掉链接中的page属性
因为$page在url中,不能直接改变它的值,需要通过字符串的方式,先将他的值去掉,然后再拼接上:
//将uri的page去掉
private function getUri(){
//第一步.获取当前页面的url,检查是否由如果没有问号,加上问号
$uri=$_SERVER['REQUEST_URI'].(strpos($_SERVER['REQUEST_URI'],'?')?'':'?');
//parse_url将当前url转换成数组格式
$parse=parse_url($uri);
//第二步.去掉url里的page属性,然后重新拼接起来
if(isset($parse['query'])){
parse_str($parse['query'],$params);
unset($params['page']);
}
$url=$parse['path'].'?'.http_build_query($params);
//parse_url:将url转成有path和query两个属性的数组
//parse_str("page=10",$param)将字符串解析成多个变量存入数组$param中
//http_build_query将数组类型转为字符串类型
return $uri;
}
函数的返回值将赋给$uri变量
点击跳转的功能
用字符串拼接出一个链接,打印在屏幕上,需要注意的是链接的地址:
这个时候$uri就有用了,首页链接的地址就是$uri + '&page=1'
//首页 private function first(){ if ($this->page==1) return ''; else return "<a href='{$this->uri}&page=1'>首页</a> "; }
尾页,链接的地址就是$uri + '&page=页数'
<a href='{$this->uri}&page=$lastpage'>尾页</a>
上一页下一页的链接就是当前的page+1,当前的page-1,与首页末页的区别就是要做一下判断,如果当前是第一页就不能点击上一页,当前是最后一页就不能点击下一页
为了体现良好模块化,链接的文字内容应该封装在一个字符串中:
private $config=array("header"=>"新闻","unit"=>"条","prev"=>"上一页","next"=>"下一页","first"=>"首页","last"=>"尾页");
代码就是这样:
//上一页 private function prev() { if ($this->page == 1) return "{$this->config['prev']}"; else { $prevpage=$this->page-1; return "<a href='{$this->uri}&page=$prevpage'>{$this->config['prev']}</a> "; } }
页码设置
三个字符串,前一个是循环输出页码数量的一半向下取整,中间是当前页不加链接,后一个循环输出是当前页之后的一半向下取整
//设置页码: //第一个循环,显示总数向下取整floor(5)=2次,显示当前页-2,当前页-1 //第二个循环,显示总数向下取整floor(5)=2次,当前页+1,当前页+2 private function partList(){ $linkpage=''; $inum=floor($this->listNum/2); for($i=$inum;$i>=1;$i--){ $page=$this->page-$i; if($page>=1){ $linkpage.="<a href='{$this->uri}&page={$page}'>{$page}</a> "; } } $linkpage.="{$this->page} "; for($i=1;$i<=$inum;$i++){ $listpage=$this->page+$i; if ($listpage<=$this->pageNum){ $linkpage.="<a href='{$this->uri}&page={$listpage}'>{$listpage}</a> "; } } return $linkpage; }
跳转到第X页功能
这个要借助js实现:
点击跳转按钮时,触发事件函数:
获取input框中的内容,将其作为$page的值拼接到uri上
然后通过location方法跳转到拼接好的uri对应的页面
private function gopage(){ $go="到第<input type='text' class='goinput' style='width:28px;'>页 <button class='goBn'>跳转</button>"; $go.="<script> var goBn = document.querySelector('.goBn'); goBn.onclick=function(){ var go = document.querySelector('.goinput').value; if(go<{$this->pageNum}&&go>0){ var gohref = new String(\"{$this->uri}&page=\"); var gohref=gohref+go; location=gohref; } } </script>"; return $go; }
四.完整的代码如下:
分页类page.php
<?php class page{ private $total;//总记录数 private $listRows;//每页显示行数 private $uri;//uri private $page;//当前页 private $limit;//sql语句的limit限制 private $pageNum;//总页数 private $listNum=5;//页码数 private $config=array("header"=>"新闻","unit"=>"条","prev"=>"上一页","next"=>"下一页","first"=>"首页","last"=>"尾页"); public function __construct($total,$listRows=10){ $this->total=$total; $this->listRows=$listRows; $this->uri=$this->getUri(); $this->page=empty($_GET['page'])?1:$_GET['page']; //获取页数:总数除以每页uri记录数向上取整 $this->pageNum=ceil($this->total/$this->listRows); $this->limit=$this->setLimit(); } function __get($args) { if ($args=="limit"){ return $this->limit; } else return null; } //将uri的page去掉 private function getUri(){ //获取当前页面的url,检查是否有问号,如果没有问号,加上问号 $uri=$_SERVER['REQUEST_URI'].(strpos($_SERVER['REQUEST_URI'],'?')?'':'?'); //parse_url将当前url转换成数组格式 $parse=parse_url($uri); //去掉url里的page属性,然后重新拼接起来 if(isset($parse['query'])){ parse_str($parse['query'],$params); unset($params['page']); } $url=$parse['path'].'?'.http_build_query($params); //parse_url:将url转成有path和query两个属性的数组 //parse_str("page=10",$param)将字符串解析成多个变量存入数组$param中 //http_build_query将数组类型转为字符串类型 return $url; } //当前页从第几个开始显示,显示多少个 private function setLimit() { return 'Limit' .' '.($this->page - 1) * $this->listRows .','."{$this->listRows}"; } //获取当前页的第一条和最后一条显示的行号 private function start(){ if($this->total==0) return 0; else return ($this->page - 1) * $this->listRows+1; } private function end(){ return min($this->total,$this->page*$this->listRows); } //首页 private function first(){ if ($this->page==1) return ''; else return "<a href='{$this->uri}&page=1'>{$this->config['first']}</a> "; } //上一页 private function prev() { if ($this->page == 1) return "{$this->config['prev']}"; else { $prevpage=$this->page-1; return "<a href='{$this->uri}&page=$prevpage'>{$this->config['prev']}</a> "; } } //下一页 private function next() { if ($this->page == $this->pageNum) return "{$this->config['next']}"; else { $nextpage=$this->page+1; return "<a href='{$this->uri}&page=$nextpage'>{$this->config['next']}</a> "; } } //尾页 private function last() { if ($this->page == $this->pageNum) return ''; else { $lastpage=$this->pageNum; return "<a href='{$this->uri}&page=$lastpage'>{$this->config['last']}</a> "; } } //设置页码: //写两个循环,前一个是当前页之前的一半,中间是当前页不加链接,后一个是当前页之后的一半 //第一个循环,显示总数向下取整floor(5)=2次,显示当前页-2,当前页-1 //第二个循环,显示总数向下取整floor(5)=2次,当前页+1,当前页+2 private function partList(){ $linkpage=''; $inum=floor($this->listNum/2); for($i=$inum;$i>=1;$i--){ $page=$this->page-$i; if($page>=1){ $linkpage.="<a href='{$this->uri}&page={$page}'>{$page}</a> "; } } $linkpage.="{$this->page} "; for($i=1;$i<=$inum;$i++){ $listpage=$this->page+$i; if ($listpage<=$this->pageNum){ $linkpage.="<a href='{$this->uri}&page={$listpage}'>{$listpage}</a> "; } } return $linkpage; } private function gopage(){ $go="到第<input type='text' class='goinput' style='width:28px;'>页 <button class='goBn'>跳转</button>"; $go.="<script> var goBn = document.querySelector('.goBn'); goBn.onclick=function(){ var go = document.querySelector('.goinput').value; if(go<{$this->pageNum}&&go>0){ var gohref = new String(\"{$this->uri}&page=\"); var gohref=gohref+go; location=gohref; } } </script>"; return $go; } //显示的当前页面内容 function fpage($checkHtml=array(1,2,3,4,5,6,7,8,9,10)){ $html[1]="共有{$this->total}{$this->config['unit']}{$this->config['header']} "; $html[2]="本页{$this->start()}条到{$this->end()}条 "; $html[3]="当前为{$this->page}/{$this->pageNum}页 "; $html[4]="{$this->first()}"; $html[5]="{$this->prev()}"; $html[6]="{$this->next()}"; $html[7]="{$this->last()} "; $html[8]="{$this->partList()} "; $html[9]="{$this->gopage()}"; $html[10]=" "; $showhtml=''; foreach($checkHtml as $i){ $showhtml.=$html[$i]; } return $showhtml; } }
messageboard.php
<?php header("Content-type: text/html; charset=utf-8"); include 'page.php'; try { $pdoObj = new PDO("mysql:host=localhost;dbname=zhangkwebsite", 'root', 'root'); $pdoObj->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); }catch(PDOException $p){ echo '数据库连接失败'.$p->getMessage(); } try{ echo '<table align="center" border="1" width="1000">' ."<tr><th colspan='2'>新闻浏览</th></tr>"; $query=$pdoObj->query("select count(*) from messageboard"); $val=$query->fetch(PDO::FETCH_ASSOC); $ncount=$val['count(*)']; $p=new page(100,5); $query=$pdoObj->query("select * from messageboard {$p->limit}"); while($val=$query->fetch(PDO::FETCH_ASSOC)){ echo '<tr>'; echo '<td>'.$val["id"].'</td>'; echo '<td>'.$val["title"].'</td>'; echo '</tr>'; } echo "<tr><td colspan='2' style='text-align: right'>{$p->fpage()}</td></tr></table>"; } //query("select * from account where account=$XX and pwd=YY"); //query("select * from account where account=:account and pwd=:pwd",['account'=>$xx,'']); //query("select * from account where account=? and pwd=?"); //sprintf(select * from account where account=%d and pwd=%s,['']) catch(PDOException $e){ echo '错误'.$e->getMessage(); }