博客列表 >【PHP动态分页】composer自动加载机制和第三方验证码库的使用以及数据动态分页的原理与实现(附源码)

【PHP动态分页】composer自动加载机制和第三方验证码库的使用以及数据动态分页的原理与实现(附源码)

 一纸荒凉* Armani
 一纸荒凉* Armani原创
2021年05月21日 15:44:561024浏览

第三方验证码库的使用

常用 composer 包推荐 https://www.php.cn/tool/composer/431956.html

  1. composer install - 如有 composer.lock 文件,直接安装,否则从 composer.json 安装最新扩展包和依赖;
  2. composer update - composer.json 安装最新扩展包和依赖;
  3. composer update vendor/package - composer.json 或者对应包的配置,并更新到最新;
  4. composer require new/package - 添加安装 new/package, 可以指定版本,如: composer require new/package ~2.5.

这里演示一下使用composer装一个验证码的包,并调用类库生成随机验证码

  1. "require": {
  2. "gregwar/captcha": "^1.1"
  3. }

生成验证码

  1. <?php
  2. session_start();
  3. header('Content-type: image/jpeg');
  4. require '../vendor/autoload.php';
  5. use Gregwar\Captcha\CaptchaBuilder;
  6. $builder = new CaptchaBuilder();
  7. $builder->build()->save('out.jpg');
  8. $_SESSION['phrase'] = $builder->getPhrase();
  9. // echo $_SESSION['phrase'];
  10. $builder->output();
  11. ?>

引入验证码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <input type="text" name="" width="150" placeholder="请输入验证码">
  9. <img src="index.php" onclick="this.src='index.php'" width="120">
  10. </body>
  11. </html>

composer 自动加载机制

为了描述包的自动加载信息, Composer 会生成一个 vendor/autoload.php 文件,你可以简单的 include 这个文件,并在无需其它额外工作的情况下就可以使用这些包所提供的类:

  1. // Composer提供了自动加载的特性,只需在你的代码的初始化部分中加入下面一行:
  2. require 'vendor/autoload.php';

在你的项目中加入这段引入文件

  1. require __DIR__ . '/vendor/autoload.php';
  2. use Gregwar\Captcha\CaptchaBuilder;
  3. $builder = new CaptchaBuilder();
  4. $builder->build()->save('out.jpg');

你也可以在 composer.json 中添加一个 autoload 指令,来添加自己的自动加载声明

目录文件结构如下:

app\controller\Auth.php

  1. // 命名空间和路径一致
  2. namespace app\controller;
  3. // 类名和文件名一致
  4. class Auth {
  5. public static function hello()
  6. {
  7. return __METHOD__;
  8. }
  9. }

自动加载配置:autoload;在json配置文件中”autoload”字段中的配置方式

  • 文件级“files”:[];把需要自动加载的文件写入数组中即可
  • 目录级“classmap”:[]把需要加载文件的目录写入数组中即可
  • 空间级“psr-4”:[]把需要自动加载的类的命名空间映射到目录,以键值的方式写入数组中
  • 最后要执行一下”composer dump-autoload”,更新 composer.json 中的 autoload 配置项
  1. "autoload": {
  2. "files": [
  3. "app/controller/User.php",
  4. "extend/lib/Order.php"
  5. ],
  6. "classmap": [
  7. "app/controller",
  8. "extend/lib"
  9. ],
  10. "psr-4": {
  11. "app\\controller\\": "app/controller",
  12. "extend\\lib\\": "extend/lib"
  13. }
  14. }

Composer 会为 app/controller 命名空间注册一个 PSR-4 的自动加载.

你定义一个命名空间指向目录的映射。 在 vendor 目录同级的app/controller 目录将成为你项目的根目录。文件名 app/controller/Auth.php 需包含 Auth 类。

添加 autoload 指令之后,你必需重新运行 composer dump-autoload 来重新生成 vendor/autoload.php 文件。

  1. <?php
  2. /* spl_autoload_register(function($className){
  3. require $className . '.php';
  4. }); */
  5. //composer自动加载功能
  6. /**
  7. * 1. 在composer.json中添加autoload字段 files 可以加载任意位置的类文件
  8. "files": [
  9. "app/controller/User.php",
  10. "extend/lib/Order.php"
  11. ]
  12. 修改完成以后, 必须执行composer dump-autoload命令才能生效
  13. * 2. 在composer.json中添加autoload字段 classmap 类映射 实现类的批量注册
  14. *
  15. * "classmap": [
  16. "app/controller",
  17. "extend/lib"
  18. ]
  19. 修改完成以后,或者往绑定的目录中添加新类时, 依然 必须执行composer dump-autoload命令才能生效
  20. * 3.psr-4规范 : 类的命名空间与类所在的目录进行绑定,命名空间最后必须以"\" 空间分隔符结尾 ,往绑定的目录中添加新类时, 不必执行composer dump-autoload命令就能生效
  21. "psr-4": {
  22. "app\\controller\\": "app/controller",
  23. "extend\\lib\\": "extend/lib"
  24. }
  25. */
  26. require_once __DIR__ . '\\vendor\\autoload.php';
  27. use app\controller\User;
  28. use extend\lib\Order;
  29. use extend\lib\Player;
  30. use app\controller\Login;
  31. use app\controller\Auth;
  32. echo User::hello(),'<br>';
  33. echo Order::hello(),'<br>';
  34. echo Player::hello(),'<br>';
  35. echo Login::hello(),'<br>';
  36. echo Auth::hello(),'<br>';

动态分页原生实现原理

在网站中,如果list列表页内容太多,一般会设置分页功能,今天我们一起来研究一下分页原理,通过一个小案例实现这个功能.

首先我们来看看分页的逻辑:首先我们要确定首页和尾页的限制,首页必须限定在1,尾页限制的数字,需要结合我们的数据库的数据条数,和每页的显示数量。尾页=ceil(数据库总条数/每页显示的数量),向上取整。这就是我们尾页的限制数字。接下来我们就要控制数字出现的规律了。如图所示:

如果我们设定显示10个页码数,那么当我们点击页码,当前页小于或者等于5页的时候,最后的页码标签数是一直停留在10页的位置(假设尾页没有限制的情况下),当点击的页数大于5时,随着我们的点击,页码也在往后推移,于是就出现了下面的规律,尾页=当前点击页+5,首页为尾页-9.通过这个规则我们可以书写出尾页和首页的范围。$endpage为我们总页数的显示,也就是尾页的数量。

  1. // $totalpage 总页数
  2. $totalpage = 18;
  3. // $startPage 开始页码
  4. $startPage = 1;
  5. // $showPages 页码条个数
  6. $showPages = 10;
  7. // $endpage 结束页码
  8. $endPage = $showPages;
  9. // 偏移量
  10. $offsetPage = $showPages/2;
  11. // 当前页码数
  12. $curpage = empty($_GET["pageNum"])?1:$_GET["pageNum"];
  13. // curPage 当前页
  14. if($curpage <= $offsetPage+1){
  15. $startPage =1;
  16. // 假设就4页 页码数大于了总页数 结束页码则等于总页数
  17. $endPage = $endPage>=$totalpage?$totalpage:$endPage;
  18. }else{
  19. // 假设结束页码大于了总页数 那么久等于总页数
  20. $endPage = $curpage+$offsetPage>$totalpage?$totalpage:$curpage +$offsetPage;
  21. // 开始页码数为结束的页码数减去页码个数减一
  22. $startPage =$endPage-($showPages-1)<=1?1:$endPage-($showPages-1);
  23. }

首先,我们需要准备在数据库里面准备一个表,并且插入数据,这些都是必需的前提工作了,不多说。

w2jdNu.png

我们需要分页的话,需要用到 “select * from student limit num1,num2”;这是一个限定查询的语句,后面跟两个参数,num1为从第几个开始查找,num2为查找的信息的个数。

假设数据库表明为list 每页取10条数据

  1. 第一页 select * from list limit 0,10;
  2. 第二页 select * from list limit 10,10;
  3. 第三页 select * from list limit 20,10;
  4. 第四页 select * from list limit 30,10;
  5. ...
  6. n select * from list limit (n-1)*10,10;
  7. 根据页数取数据公式
  8. select * from list limit ($page-1)*$pagesize,$pagesize
  9. $page是当前的页数 $pagesize是每页取得条数

1、建立一个函数,用来实现限制查询的功能

首先我们来想一下,实现这个功能我们首先要知道当前的页数和要限制的一个页面显示几条信息,这个可以用形参传过来。那么,

我们设置pageNum为页数,pageSize为一个页面显示几条数据,在 “select * from student limit num1,num2”这个查询语句中,

num1就是(pageNum-1)*pageSize,num2就是pageSize,明白了这个关系之后,那么就好办了,代码在下面:

  1. //封装分页的函数
  2. /*
  3. * @$pageNum [数字] 当前页码数
  4. * @$pageNum [数字] 每页显示数量
  5. * return 分页的数据列表
  6. */
  7. function news($pageNum = 1, $pageSize = 5){
  8. $dns = 'mysql:host=localhost;dbname=mydb';
  9. $params = [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC];
  10. $pdo = new PDO($dns,'root','root',$params);
  11. // 计算每一页第一条记录的显示偏移量
  12. // 偏移量 = (页码-1)*每页的显示数量
  13. $offset = ($pageNum-1)*$pageSize;
  14. // 获取分页数据
  15. // limit为约束显示多少条信息,后面有两个参数,第一个为从第几个开始,第二个为长度
  16. $sql = "select sno,sname,ssex from student order by sno asc limit {$pageSize} offset {$offset}";
  17. $stmt = $pdo->query($sql);
  18. return $students = $stmt->fetchAll();
  19. }

2、建立第二个函数,用来显示总页数的函数

  1. //显示总页数的函数
  2. function allNews(){
  3. $dns = 'mysql:host=localhost;dbname=mydb';
  4. $params = [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC];
  5. $pdo = new PDO($dns,'root','root',$params);
  6. // 获取总页数
  7. $total = $pdo->query("select sno from student")->fetchAll();
  8. // 31条/每页5 向上取整就是7页
  9. return $pages = ceil(count($total)/$num);
  10. }

3、调用这两个函数,进行初步的处理

我们想做下一页、下一页的结果,需要用到get方法在本页面传数据,那么我们在刷新页面的时候,肯定get是得不到数据的,所以需要用三目运算了。

  1. <?php
  2. $allNum = allNews(); // 总页数
  3. $pageSize = 6; //约定每页显示的信息条数
  4. // 当前第几页
  5. $pageNum = empty($_GET["pageNum"])?1:$_GET["pageNum"];
  6. $endPage = $allNum; //总页数
  7. // 列表数据
  8. $listStudents = news($pageNum,$pageSize);
  9. ?>

4、在页面进行显示

在页面显示的话,需要用到了foreach循环了,代码简单,看下面:

  1. <table>
  2. <caption>学生信息表</caption>
  3. <thead>
  4. <tr>
  5. <td>学号</td>
  6. <td>姓名</td>
  7. <td>性别</td>
  8. <td>操作</td>
  9. </tr>
  10. </thead>
  11. <tbody>
  12. <?php foreach($listStudents as $user):?>
  13. <tr>
  14. <td><?= $user['sno']?></td>
  15. <td><?= $user['sname']?></td>
  16. <td><?= $user['ssex']?></td>
  17. <td><button>删除</button><button>编辑</button></td>
  18. </tr>
  19. <?php endforeach;?>
  20. </tbody>
  21. </table>

5、实现首页上一页,下一页尾页的效果

要实现页面跳转的效果,我们需要用到了a标签的href属性,地址写“?pageNum = …”这个pageNum是我们自己定义的,由于是get来传递的,在上一步里面我们已经用$_GET接受了参数,所以我们只需要进行get的参数传递就可以了;

  1. URL链接:http://zhang.com/0519/composer/paging/index.php?p=10
  2. $_SERVER['PHP_SELF'] 可以获取/0519/composer/paging/index.php
  3. $_SERVER['REQUEST_URI'] 可以获取/0519/composer/paging/index.php?p=10
  4. $_SERVER['HTTP_REFERER'] 可以获取http://zhang.com/0519/composer/paging/index.php?p=10

首页:“pageNum=1”;

上一页:pageNum=<?php echo $pageNum==1?1:$pageNum-1?>

下一页:pageNum=<?php echo $pageNum==$endPage ?$endPage :$pageNum+1?>

尾页:pageNum=<?php echo $pageNum =$endPage?>;

需要通过判断当前是否在第一页或者最后一页,对跳转a标签进行修饰操作,代码如下:

  1. <!-- 首页 上一页 -->
  2. <?php $prev=$pageNum-1; if($pageNum == 1) $prev = 1;?>
  3. <a href="<?=$pageNum!= 1? '?pageNum=1' : 'javascript:;' ?>">首页</a>
  4. <a href="<?=$pageNum!= 1? '?pageNum='.$prev : 'javascript:;' ?>">上一页</a>
  5. <!-- 下一页 尾页 -->
  6. <?php $next=$pageNum+1; if($pageNum == $endPage) $next=$pageNum;?>
  7. <a href="<?=$pageNum!=$endPage? '?pageNum='.$next : 'javascript:;' ?>">下一页</a>
  8. <a href="<?=$pageNum!=$endPage? '?pageNum='.$endPage : 'javascript:;' ?>" >尾页</a>

6、渲染页数标签123456的跳转翻页效果

通过判断页数标签是否与当前地址栏页数一致,为其添加选中样式,每个跳转数字标签的a链接地址为?pageNum=$i循环的总页数

  1. <!-- 首页 上一页 -->
  2. <?php $prev=$pageNum-1; if($pageNum == 1) $prev = 1;?>
  3. <a href="<?=$pageNum!= 1? '?pageNum=1' : 'javascript:;' ?>">首页</a>
  4. <a href="<?=$pageNum!= 1? '?pageNum='.$prev : 'javascript:;' ?>">上一页</a>
  5. <!-- 页数按钮 1 2 3 4 5 分页跳转页数字 -->
  6. <?php for ($i=1; $i <=$endPage ; $i++) :?>
  7. <a class="<?=$i==$pageNum?'active':''?>" href="<?='?pageNum='.$i?>"><?=$i?></a>
  8. <? endfor;?>
  9. <!-- 下一页 尾页 -->
  10. <?php $next=$pageNum+1; if($pageNum == $endPage) $next=$pageNum;?>
  11. <a href="<?=$pageNum!=$endPage? '?pageNum='.$next : 'javascript:;' ?>">下一页</a>
  12. <a href="<?=$pageNum!=$endPage? '?pageNum='.$endPage : 'javascript:;' ?>" >尾页</a>

7、难点:页标签的起点数和总点数 显示数组两侧标签的省略号

设置显示几个跳转数字标签,当前页数大于页数标签的一半加一时候

  1. // $totalpage 总页数
  2. $totalpage = 18;
  3. // $startPage 开始页码
  4. $startPage = 1;
  5. // $showPages 页码条个数
  6. $showPages = 10;
  7. // $endpage 结束页码
  8. $endPage = $showPages;
  9. // 偏移量
  10. $offsetPage = $showPages/2;
  11. // 当前页码数
  12. $curpage = empty($_GET["pageNum"])?1:$_GET["pageNum"];
  13. // curPage 当前页
  14. if($curpage <= $offsetPage+1){
  15. $startPage =1;
  16. // 假设就4页 页码数大于了总页数 结束页码则等于总页数
  17. $endPage = $endPage>=$totalpage?$totalpage:$endPage;
  18. }else{
  19. // 假设结束页码大于了总页数 那么久等于总页数
  20. $endPage = $curpage+$offsetPage>$totalpage?$totalpage:$curpage +$offsetPage;
  21. // 开始页码数为结束的页码数减去页码个数减一
  22. $startPage =$endPage-($showPages-1)<=1?1:$endPage-($showPages-1);
  23. }

当触发修改开始页码和结束页码数时候,则在前后分别显示省略号。

开始页码数大于1的时候前面显示省略号,结束页码数小于总页数的时候后面显示省略号,效果如下:

gTS8iR.png
gTS1o9.png
gTSldJ.png

从上图可以看出总页数为13页,页码条个数为5个,也就是当前页码数大于3的时候触发,左右偏移量为2

  1. if($startPage>1){
  2. $startOmit = '...';
  3. }
  4. if($endPage<$totalpage){
  5. $endOmit = '...';
  6. }
  7. // 首部省略号
  8. <?php if(isset($startOmit)):?>
  9. <a href="javascript:;"><?=$startOmit?></a>
  10. <?endif?>
  11. // 尾部省略号
  12. <?php if(isset($endOmit)):?>
  13. <a href="javascript:;">...</a>
  14. <?endif?>

动态分页原生实现流程

1.获取当前url字符串,并用parse_url解析得到url数组

2.连接服务器,获取list页将要展示的内容集合,统计总共展示的条数,进而算出总共多少页内容

3.判断页面是否是提交状态,如果不是默认为第一页

4.将计算的limit起始位置赋值给变量$page

5.使用$page和$pageSize去数据库取数据

6.循环便利得数据集合,输出展示在页面上

gTQmSf.png
gTQZfP.png
gTQnl8.png
gTQVYt.png

完整数据查询数据分页代码

  1. <? require './pageData.php' ?>
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8. <title>学生信息表</title>
  9. <link rel="stylesheet" href="style.css">
  10. </head>
  11. <body>
  12. <table>
  13. <caption>学生信息表</caption>
  14. <thead>
  15. <tr>
  16. <td>学号</td>
  17. <td>姓名</td>
  18. <td>性别</td>
  19. <td>操作</td>
  20. </tr>
  21. </thead>
  22. <tbody>
  23. <?php foreach($students as $user):?>
  24. <tr>
  25. <td><?= $user['sno']?></td>
  26. <td><?= $user['sname']?></td>
  27. <td><?= $user['ssex']?></td>
  28. <td><button>删除</button><button>编辑</button></td>
  29. </tr>
  30. <?php endforeach;?>
  31. </tbody>
  32. </table>
  33. <?php
  34. //讨论省略点分页 前提: 两边的省略点都出现的时候
  35. //分页条显示的页数
  36. $showPages = 5;
  37. //分页条的开始页码值
  38. $startPage = 1;
  39. //分页条的结束页码值
  40. $endPage = $showPages;
  41. //分页条的终止页码相对于当前页码的偏移量: 1 2 3 4 5 偏移量2
  42. $offset = ($showPages-1)/2;
  43. // 分页条显示的页数小于总页数时
  44. if($showPages < $pages)
  45. { // 当前页码大于偏移量+1 也就是第3也往后
  46. if($page > $offset+1)
  47. { // 第三页往后前端显示省略号
  48. $startOmit = '...';
  49. // 开始页码为当前页码-2 也就是2开始
  50. $startPage = $page-$offset;
  51. // 结束的页码为当前页码+2 也就是6结束
  52. $endPage = $page+$offset;
  53. // 如果结束的页码值大于了总共的页数,结束的页码就为总页数
  54. if($endPage > $pages){$endPage=$pages;}
  55. }else{
  56. // 如果没有大于3 也就是第1 2 3页 开始为1 结束为5
  57. $startPage = 1;
  58. $endPage = $showPages;
  59. }
  60. // 分页条个数小于总页数并且总页数大于当前页码+偏移量2 也就是结束页码没有到总页数
  61. if($showPages<$pages && $page + $offset < $pages)
  62. // 就是没有到总页数的时候右端显示省略号
  63. $endOmit = '...';
  64. }else{
  65. // 当分页条显示的页数大于了总页数 例如显示5个分页条 但只有4页
  66. $endPage = $pages; // 结束页码就为总页数
  67. }
  68. ?>
  69. <!-- 动态生成分页条 跳转地址 当前页码的高亮显示 -->
  70. <p class="page">
  71. <!-- 首页 上一页 -->
  72. <?php $prev=$page-1; if($page == 1) $prev = 1;?>
  73. <a href="<?=$page != 1?'?p=1':'javascript:;'?>" style="<?=$page==1?'cursor: no-drop;':'' ?>">首页</a>
  74. <a href="<?=$page != 1?'?p='.$prev:'javascript:;'?>" style="<?=$page==1?'cursor: no-drop;':'' ?>">上一页</a>
  75. <?php if(isset($startOmit)):?>
  76. <a href="javascript:;"><?=$startOmit?></a>
  77. <?endif?>
  78. <!-- 1 2 3 4 5 分页跳转页数字 -->
  79. <?php for ($i=$startPage; $i <=$endPage ; $i++) :?>
  80. <a class="<?=$i==$page?'active':''?>" href="<?='?p='.$i?>"><?=$i?></a>
  81. <? endfor;?>
  82. <?php if(isset($endOmit)):?>
  83. <a href="javascript:;">...</a>
  84. <?endif?>
  85. <!-- 下一页 尾页 -->
  86. <?php $next=$page+1; if($page == $pages) $next=$page;?>
  87. <a href="<?=$page != $pages?'?p='.$next:'javascript:;'?>" style="<?=$page==$pages?'cursor: no-drop;':'' ?>">下一页</a>
  88. <a href="<?=$page != $pages?'?p='.$pages:'javascript:;' ?>" style="<?=$page==$pages?'cursor: no-drop;':'' ?>">尾页</a>
  89. </p>
  90. </body>
  91. </html>

通过页码请求数据库列表内容

  1. <?php
  2. $dns = 'mysql:host=localhost;dbname=mydb';
  3. $params = [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC];
  4. $pdo = new PDO($dns,'root','root',$params);
  5. // 获取分页数据:每页显示的数量,当前的页数-------------
  6. // 每页显示的数量
  7. $num = 5;
  8. // 当前页码 默认为1
  9. $page = $_GET['p']??'1';
  10. // 计算每一页第一条记录的显示偏移量
  11. // 偏移量 = (页码-1)*每页的显示数量
  12. $offset = ($page-1)*$num;
  13. // 获取分页数据
  14. $sql = "select sno,sname,ssex from student order by sno asc limit {$num} offset {$offset}";
  15. $stmt = $pdo->query($sql);
  16. $students = $stmt->fetchAll();
  17. // 获取总页数
  18. $total = $pdo->query("select sno from student")->fetchAll();
  19. $pages = ceil(count($total)/$num);
  20. ?>

style.css

  1. * {
  2. margin: 0;
  3. padding: 0;
  4. box-sizing: border-box;
  5. color: #555;
  6. }
  7. body {
  8. display: flex;
  9. flex-direction: column;
  10. align-items: center;
  11. }
  12. /*表格样式*/
  13. table {
  14. width: 80%;
  15. border: 1px solid;
  16. border-collapse: collapse;
  17. text-align: center;
  18. }
  19. table caption {
  20. font-size: 1.2rem;
  21. margin: 10px;
  22. }
  23. table td,
  24. table th {
  25. border: 1px solid;
  26. padding: 5px;
  27. }
  28. table tr:hover {
  29. background-color: #eee;
  30. }
  31. table thead tr:only-of-type {
  32. background-color: lightblue;
  33. }
  34. table button {
  35. width: 56px;
  36. height: 26px;
  37. }
  38. table button:last-of-type {
  39. color: red;
  40. }
  41. table button {
  42. cursor: pointer;
  43. margin: 0 3px;
  44. }
  45. /*分页条样式*/
  46. body > p {
  47. display: flex;
  48. }
  49. p > a {
  50. text-decoration: none;
  51. color: #555;
  52. border: 1px solid;
  53. padding: 5px 10px;
  54. margin: 10px 2px;
  55. }
  56. .active {
  57. background-color: rgba(206, 11, 5, 0.787);
  58. color: white;
  59. border: 1px solid rgba(206, 11, 5, 0.787);
  60. }

请求三方接口新闻分页

  1. <?php
  2. $url = "http://v.juhe.cn/toutiao/index?";
  3. $key = '0d335db5787ed2043070c89c1dd25404'; // 接口key
  4. $type = 'top'; // 新闻类型
  5. $page = $_GET['p']??'1'; // 当前页数
  6. $page_size = 12; // 每页返回条数
  7. $pages = 30; //总页数
  8. $query = http_build_query(['type'=>$type,'page'=>$page,'page_size'=>$page_size,'key'=>$key]);
  9. $str = file_get_contents($url.$query);
  10. $json = json_decode($str,true);
  11. $list = $json['result']['data'];
  12. ?>
  13. <!DOCTYPE html>
  14. <html lang="en">
  15. <head>
  16. <meta charset="UTF-8">
  17. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  18. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  19. <title>新闻列表</title>
  20. <link rel="stylesheet" href="style.css">
  21. </head>
  22. <body>
  23. <table>
  24. <caption>新闻列表</caption>
  25. <thead>
  26. <tr>
  27. <td>日期</td>
  28. <td>标题</td>
  29. <td>作者</td>
  30. <td>操作</td>
  31. </tr>
  32. </thead>
  33. <tbody>
  34. <?php foreach($list as $item):?>
  35. <tr>
  36. <td><?= $item['date']?></td>
  37. <td><?= $item['title']?></td>
  38. <td><?= substr($item['author_name'], 0,12)?></td>
  39. <td><?= '<a href="'.$item["url"].'">点击浏览</a>'?></td>
  40. </tr>
  41. <?php endforeach;?>
  42. </tbody>
  43. </table>
  44. <?php
  45. //讨论省略点分页 前提: 两边的省略点都出现的时候
  46. //分页条显示的页数
  47. $showPages = 5;
  48. //分页条的开始页码值
  49. $startPage = 1;
  50. //分页条的结束页码值
  51. $endPage = $pages;
  52. //分页条的终止页码相对于当前页码的偏移量:
  53. $offset = ($showPages-1)/2;
  54. if($showPages < $pages)
  55. {
  56. if($page > $offset+1)
  57. {
  58. $startOmit = '...';
  59. $startPage = $page-$offset;
  60. $endPage = $page+$offset;
  61. if($endPage > $pages){$endPage=$pages;}
  62. }else{
  63. $startPage = 1;
  64. $endPage = $showPages;
  65. }
  66. if($showPages<$pages && $page + $offset < $pages)
  67. $endOmit = '...';
  68. }
  69. ?>
  70. <!-- 动态生成分页条 跳转地址 当前页码的高亮显示 -->
  71. <p class="page">
  72. <!-- 首页 上一页 -->
  73. <?php if($page == 1) $prev = 1; if($page != 1):?>
  74. <a href="<?='?p=1'?>">首页</a>
  75. <a href="<?='?p='.$prev=$page-1?>">上一页</a>
  76. <?endif;?>
  77. <?php if(isset($startOmit)):?>
  78. <a href="javascript:;"><?=$startOmit?></a>
  79. <?endif?>
  80. <!-- 1 2 3 4 5 分页跳转页数字 -->
  81. <?php for ($i=$startPage; $i <=$endPage ; $i++) :?>
  82. <a class="<?=$i==$page?'active':''?>" href="<?='?p='.$i?>"><?=$i?></a>
  83. <? endfor;?>
  84. <?php if(isset($endOmit)):?>
  85. <a href="javascript:;"><?=$endOmit?></a>
  86. <?endif?>
  87. <!-- 下一页 尾页 -->
  88. <?php if($page == $pages) $next=$page; if($page != $pages) :?>
  89. <a href="<?='?p='.$next=$page+1?>">下一页</a>
  90. <a href="<?='?p='.$pages?>">尾页</a>
  91. <?endif;?>
  92. </p>
  93. </body>
  94. </html>

g7t58J.png
g7tI29.png

前端动态无刷新分页

前后端分离式开发中,我们的数据往往是通过接口进行请求而来的,这时候就需要前端渲染时进行分页获取数据信息。

注意的是前端使用ajax可以实现局部刷新分页,但是不利于seo,无法通过链接保存,一般用于网站后台的数据分页。

一、无刷新分页

1.实现原理:前端通过ajax请求获取服务器数据,再由JS把数据组成html渲染到页面中

2.服务器php代码(获取分页数据信息)

  1. <?php
  2. //链接数据库操作
  3. $dns = 'mysql:host=localhost;dbname=mydb';
  4. $params = [PDO::ATTR_ERRMODE=>PDO::ERRMODE_WARNING,PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC];
  5. $pdo = new PDO($dns,'root','root',$params);
  6. //获取当前数据记录总条数
  7. $sql="select count(*) as 'nums' from student;";
  8. $stmt=$pdo->prepare($sql);
  9. $stmt->execute();
  10. $result=$stmt->fetch();
  11. // var_dump($result);
  12. $nums=$result['nums']; // 总条数
  13. $num=10; // 每页显示记录数
  14. $pages=ceil($nums/$num);// 获取总页数
  15. // echo $pages;
  16. // 获取当前分页的数据记录信息
  17. $sql='select * from student limit ?,?;';
  18. // echo $_GET['p'];
  19. $page=$_GET['p']??1;//页码数
  20. $start=($page-1)*$num;//通过页码数获取起始记录数
  21. $stmt=$pdo->prepare($sql);
  22. $stmt->bindParam(1,$start,PDO::PARAM_INT);
  23. $stmt->bindParam(2,$num,PDO::PARAM_INT);
  24. $stmt->execute();
  25. // echo print_r($stmt->fetchAll(),true);
  26. $rows=$stmt->fetchAll();
  27. $res=['data'=>$rows,'pages'=>$pages];
  28. echo json_encode($res);
  29. // return json_encode($rows);

2.前端js获取数据请求和页面渲染

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>学生信息表(无刷新分页)</title>
  8. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  9. <style>
  10. main {
  11. width: 1000px;
  12. margin: 10px auto;
  13. }
  14. table {
  15. width: 1000px;
  16. }
  17. #page {
  18. margin-top: 10px;
  19. width: 1000px;
  20. display: flex;
  21. justify-content: space-evenly;
  22. }
  23. #page>span {
  24. width: 46px;
  25. height: 30px;
  26. background-color: lightgray;
  27. text-align: center;
  28. color: black;
  29. line-height: 30px;
  30. }
  31. #page>span:hover {
  32. cursor: pointer;
  33. background-color: white;
  34. color: red;
  35. }
  36. th,
  37. td {
  38. text-align: center;
  39. }
  40. </style>
  41. </head>
  42. <body>
  43. <main>
  44. <table border="1" cellpadding='3' cellspacing='0'>
  45. <caption>学生信息表</caption>
  46. <tr id="title">
  47. <th>学号</th>
  48. <th>姓名</th>
  49. <th>生日</th>
  50. <th>性别</th>
  51. <th>班级</th>
  52. <th>操作</th>
  53. </tr>
  54. </table>
  55. <!--页码部分 -->
  56. <div id='page'>
  57. </div>
  58. </main>
  59. <script>
  60. //页面主体内容获取和生成函数
  61. function getrows(data) {
  62. //如果页面已经记录信息需要移除
  63. if ($($("table>tbody")[0]).children().length > 1) {
  64. $($("table>tbody")[0]).children().remove("tr:not(#title)");
  65. };
  66. //生成html内容
  67. var content = "";
  68. data.forEach((item) => {
  69. content += `<tr>
  70. <td>${item["sno"]}</td>
  71. <td>${item["sname"]}</td>
  72. <td>${item["sbirthday"]}</td>
  73. <td>${item["ssex"]}</td>
  74. <td>${item["sclass"]}</td>
  75. <td><button><a href="./edit.php?id=${item["id"]}" target="_blank">编辑</a></button> <button class="delete" data-index="${item["id"]}">删除</button></td>
  76. </tr>`;
  77. });
  78. // 渲染到页面中取
  79. $('#title').after(content);
  80. }
  81. //生成分条条函数
  82. function getpage(pages) {
  83. //如果没有分页条则生成
  84. if ($("#page").children().length == 0) {
  85. var plink = "<span>首页</span>";
  86. for (var i = 1; i <= pages; i++) {
  87. plink += `<span>${i}</span>`;
  88. }
  89. plink += "<span>尾页</span>"
  90. // console.log(plink);
  91. $("#page").append(plink);
  92. }
  93. // console.log($("#page").children().length);
  94. }
  95. //ajax获取数据信息函数
  96. function getdata(page) {
  97. $.ajax({
  98. type: 'GET',
  99. url: './staffs_api.php',
  100. data: {
  101. p: page
  102. },
  103. dataType: 'json',
  104. success: function(res) {
  105. // console.log(res);
  106. var data = res['data'];
  107. var pages = res['pages'];
  108. // console.log(data, pages);
  109. //调用函数生成页面信息
  110. getrows(data);
  111. getpage(pages);
  112. }
  113. });
  114. }
  115. //首次打开页面默认获取首页数据信息并展示
  116. window.onload = function() {
  117. getdata(1);
  118. }
  119. //通过委托事件实现翻页(上一页下一页功能没有实现)
  120. $('#page').click(function(ev) {
  121. // console.log(ev.target.textContent, ev.currentTarget);
  122. var currentpage = ev.target.textContent;
  123. switch (currentpage) {
  124. case "首页":
  125. getdata(1);
  126. ev.target.style.color = 'red';
  127. break;
  128. case "尾页":
  129. var count = $(ev.currentTarget).children().length - 4;
  130. getdata(count);
  131. break;
  132. default:
  133. getdata(currentpage);
  134. }
  135. });
  136. //删除数据功能,通过ajaxComplete()函数来获取动态生成的信息
  137. $(document).ajaxComplete(function() {
  138. // console.log($('.delete'));
  139. $('.delete').click(function(ev) {
  140. var id = $(ev.target).data("index");
  141. // console.log(id);
  142. if (window.confirm("确定删除吗?")) {
  143. $.ajax({
  144. type: 'GET',
  145. url: './delete.php',
  146. data: {
  147. id: id
  148. },
  149. dataType: 'json',
  150. success: function(res) {
  151. if (res[0] > 0) {
  152. return alert("删除成功");
  153. } else {
  154. return alert("删除失败");
  155. }
  156. }
  157. });
  158. window.location.reload();
  159. } else {
  160. return false;
  161. }
  162. });
  163. });
  164. </script>
  165. </body>
  166. </html>

g7U06s.png
g7UdpQ.png

二、编辑功能

(一)功能实现原理
1.通过分页的编辑按钮获取要编辑数据记录的id,然后通过编辑页面把要编辑的记录显示出来,
2.通过ajax获取新的数据,通过id,更新信息
(二)实现代码
1.前端代码

  1. <?php
  2. include('connection.php');
  3. $sql="select * from v_staffs where id=:id;";
  4. $stmt=$pdo->prepare($sql);
  5. $id=$_GET["id"];
  6. $stmt->bindParam(':id',$id,PDO::PARAM_INT);
  7. $stmt->execute();
  8. // $stmt->debugDumpParams();
  9. $row=$stmt->fetch();
  10. // var_dump($row);
  11. // exit();
  12. ?>
  13. <!DOCTYPE html>
  14. <html lang="en">
  15. <head>
  16. <meta charset="UTF-8">
  17. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  18. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  19. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  20. <title>学生信息修改</title>
  21. </head>
  22. <body>
  23. <body>
  24. <table border="1" cellpadding='3' cellspacing='0'>
  25. <caption>修改学生信息</caption>
  26. <tr>
  27. <th>学号</th>
  28. <th>姓名</th>
  29. <th>性别</th>
  30. <th>出生日期</th>
  31. <th>班级</th>
  32. </tr>
  33. <tr>
  34. <td id="sno"><?= $row["sno"] ?></td>
  35. <td><input type="text" name="sname" value="<?= $row["sname"] ?>"></td>
  36. <td><input type="text" name="ssex" value="<?= $row["ssex"] ?>"></td>
  37. <td><input type="text" name="sbirthday" value="<?= $row["sbirthday"] ?>"></td>
  38. <td><input type="text" name="sclass" value="<?= $row["sclass"] ?>"></td>
  39. </tr>
  40. </table>
  41. <button id="update">提交</button>
  42. </body>
  43. <script>
  44. $("#update").click(function(){
  45. $.ajax({
  46. type: 'POST',
  47. url: './update.php',
  48. data: {
  49. //获取新数据
  50. sname: $("[name='sname']").val(),
  51. ssex:$("[name='ssex']").val(),
  52. sbirthday:$("[name='sbirthday']").val(),
  53. sclass:$("[name='sclass']").val(),
  54. sno:$("#sno").text()
  55. },
  56. dataType: 'json',
  57. success: function(res) {
  58. //确认更新成功
  59. alert(res[1]);
  60. window.close();//关闭窗口
  61. }
  62. });
  63. });
  64. </script>
  65. </html>

2.后端代码

  1. <?php
  2. include('connection.php');
  3. $sql="update student set sname=?,ssex=?,sbirthday=?,sclass=? where sno=?;";
  4. $stmt=$pdo->prepare($sql);
  5. $stmt->execute([$_POST['sname'],$_POST["ssex"],$_POST["sbirthday"],$_POST["sclass"],$_POST['sno']]);
  6. // $stmt->debugDumpParams();
  7. if($stmt->rowCount()>0){
  8. echo json_encode([$stmt->rowCount(),"更新成功"]);
  9. }else{
  10. echo json_encode([0,"更新失败"]);
  11. }

基于UI组件实现前端分页

本案例基于layui分页组件请求第三方新闻接口数据渲染

正如你看到对的,laypage 只负责分页本身的逻辑,具体的数据请求与渲染需要另外去完成。laypage 不仅能应用在一般的异步分页上,还可直接对一段已知数据进行分页展现,更可以取代传统的超链接分页,如果你无需考虑SEO的话(因为 laypage 的分页是JS动态生成的)。

前端要做的就是尽快接受数据并最快地展示给用户,对于数据不多的场景用前端实现也无妨,然而若考虑到以后会有成千上万条数据应用的场景,显然后端去处理分页更合适些。
每次点击下一页,前端只需发送分页数信息请求后端数据,假设一页显示十条数据,每次点击只需请求这十条数据的信息返回给前端来更快地进行交互。然而若是由前端来进行分页操作,那就得把成千上万条数据全部先拉下来,再进行操作,先不说操作这么多数据拉低的性能,光是先拉下来就得费很长时间了,所以对于数据量大的操作,一般都采用后端分页的操作更合适。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title></title>
  5. <!-- 引入 layui.css -->
  6. <link rel="stylesheet" href="//unpkg.com/layui@2.6.7/dist/css/layui.css">
  7. <!-- 引入 layui.js -->
  8. <script src="//unpkg.com/layui@2.6.7/dist/layui.js"></script>
  9. <!-- 引入 jquery.js -->
  10. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  11. </head>
  12. <body>
  13. <div class="layui-container">
  14. <table class="layui-table">
  15. <colgroup>
  16. <col >
  17. <col width="180">
  18. <col>
  19. <col>
  20. </colgroup>
  21. <thead>
  22. <tr>
  23. <th>标题</th>
  24. <th>时间</th>
  25. <th>作者</th>
  26. <th>标签</th>
  27. </tr>
  28. </thead>
  29. <tbody>
  30. </tbody>
  31. </table>
  32. <div id="page" ></div>
  33. </div>
  34. <script>
  35. layui.use('laypage', function(){
  36. var laypage = layui.laypage;
  37. //执行一个laypage实例
  38. laypage.render({
  39. elem: 'page',
  40. count: 300, //数据总数,从服务端得到
  41. limit: 10, //每页显示的条数
  42. limits: [10, 20, 30, 40, 50],
  43. jump: function(obj, first){
  44. //obj包含了当前分页的所有参数,比如:
  45. console.log(obj.curr); //得到当前页,以便向服务端请求对应页的数据。
  46. console.log(obj.limit); //得到每页显示的条数
  47. getData(obj.curr,obj.limit);
  48. }
  49. });
  50. });
  51. function getData(curr,limit){
  52. $.ajax({
  53. type: 'GET',
  54. url: 'api.php',
  55. data: {
  56. page :curr, // 当前页数
  57. page_size:limit, // 每页返回条数
  58. },
  59. dataType: "json",
  60. success: function(res) {
  61. let data = res.result.data;
  62. let html = "";
  63. data.forEach((item)=>{
  64. html += `<tr>
  65. <td>${item.title}</td>
  66. <td>${item.date}</td>
  67. <td><button class="layui-btn layui-btn-primary layui-btn-xs layui-border-blue">${item.author_name}</button></td>
  68. <td>
  69. <button type="button" class="layui-btn layui-btn-xs">${item.category}</button>
  70. <a href="${item.url}" class="layui-btn layui-btn-xs layui-btn-danger">点击查看</a>
  71. </td>
  72. </tr>`;
  73. });
  74. document.querySelector('.layui-table tbody').innerHTML = html;
  75. }
  76. });
  77. }
  78. </script>
  79. </body>
  80. </html>

接口数据

  1. <?php
  2. $url = "http://v.juhe.cn/toutiao/index?";
  3. $key = '0e0674bb2eea96ea6d8ed9657f290e73'; // 接口key
  4. $type = 'top'; // 新闻类型
  5. $page = $_GET['page']??'1'; // 当前页数
  6. $page_size = $_GET['page_size']??10; // 每页返回条数
  7. $pages = 30; //总页数
  8. $query = http_build_query(['type'=>$type,'page'=>$page,'page_size'=>$page_size,'key'=>$key]);
  9. $json = file_get_contents($url.$query);
  10. if(!empty($json)){
  11. echo $json;
  12. }
  13. ?>

g7oIKA.png
g7o4vd.png

你必须穷尽一生磨练技能,这就是成功的秘诀,也是让人家敬重的关键。

上一条:小白的PHP之路下一条:配置giehub
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议