Blogger Information
Blog 57
fans 3
comment 0
visits 60373
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHP基础-查询分页/外部对象的两种注入方式
岂几岂几
Original
741 people have browsed it

查询分页

1. 创建库表和初始数据

player数据表

初始数据(部分)

1. 数据库链接脚本connect.php

  1. <?php
  2. try {
  3. // PDO对象
  4. $pdo = new PDO('mysql:host=localhost;dbname=phpedu;port=3306;charset=utf8', 'root', 'root');
  5. } catch (Exception $e) {
  6. printf('链接异常, 异常信息: %s', $e->getMessage());
  7. die;
  8. }

2. 封装分页类pagination.php

  1. <?php
  2. class Pagination
  3. {
  4. // 第一页
  5. private $start = 1;
  6. // 一页可容纳的记录数
  7. private $pageSize = 3;
  8. // 显示的页码个数
  9. private $pageNumSize = 5;
  10. // 显示的页码列表
  11. private $pageNumList = [];
  12. // 总页数
  13. private $pageCount = 0;
  14. // 页码左右偏移量
  15. private $pageNumOffset = 0;
  16. // 当前页码
  17. private $currentPage = 1;
  18. // 记录总数
  19. private $rowCount = 0;
  20. public function __construct(int $rowCount, int $currentPage = 1, int $pageSize = 3, int $pageNumSize = 5)
  21. {
  22. // 初始化各种属性
  23. $this->rowCount = $rowCount;
  24. $this->pageSize = $pageSize;
  25. $this->pageNumSize = $pageNumSize;
  26. $this->pageNumOffset = ($pageNumSize - 1) / 2;
  27. $this->pageCount = ceil(floatval($rowCount) / $pageSize);
  28. /* 当传入的当前页码效于最小页码时,初始化为1;大于最大页码时,初始化为最大页码 */
  29. $this->currentPage = $currentPage < 1 ? 1 : ($currentPage > $this->pageCount ? $this->pageCount : $currentPage);
  30. $this->getPageNumList();
  31. }
  32. /**
  33. * 获取要显示的页码列表
  34. */
  35. private function getPageNumList()
  36. {
  37. // 如果要显示的页码数量>=总页码数量,则显示所有页码。
  38. if ($this->pageCount <= $this->pageNumSize) {
  39. $this->pageNumList = range(1, $this->pageCount, 1);
  40. return;
  41. }
  42. // 起始页码,取“当前页码-页码偏移量”和起始页码的最大值。
  43. $pageNumStart = ($this->currentPage - $this->pageNumOffset) < $this->start ? $this->start : ($this->currentPage - $this->pageNumOffset);
  44. // 结束页码,取“当前页码+页码偏移量”和总页码数的最小值。
  45. $pageNumEnd = ($pageNumStart + $this->pageNumSize - 1) > $this->pageCount ? $this->pageCount : ($pageNumStart + $this->pageNumSize - 1);
  46. // 若结束页码等于总页码,则再计算一次起始页码(避免当前页到结束页码的差值小于页码偏移量的情况)
  47. if ($pageNumEnd === $this->pageCount) {
  48. // 起始页码,取“最大页码-要显示的页码数量+1”和起始页码的最大值。
  49. $pageNumStart = ($this->pageCount - $this->pageNumSize + 1) < $this->start ? $this->start : ($this->pageCount - $this->pageNumSize + 1);
  50. }
  51. // 生成要显示的页码数组
  52. $this->pageNumList = range($pageNumStart, $pageNumEnd, 1);
  53. }
  54. // 拼接字符串,形成分页HTML代码字符串。
  55. public function getPagination()
  56. {
  57. $pageHtml = '<div class="pagination">';
  58. // 首页
  59. $tmpHtml = $this->currentPage === 1 ? '<span class="pageNum disabled">首页</span>'
  60. : sprintf('<a class="pageNum" href="%s?p=1&r=%d">首页</a>', $_SERVER['PHP_SELF'], $this->pageSize);
  61. $pageHtml .= $tmpHtml;
  62. // 上一页
  63. $tmpHtml = $this->currentPage === 1 ? '<span class="pageNum disabled">上一页</span>'
  64. : sprintf('<a class="pageNum" href="%s?p=%d&r=%d">上一页</a>', $_SERVER['PHP_SELF'], $this->currentPage - 1, $this->pageSize);
  65. $pageHtml .= $tmpHtml;
  66. // 间隔符
  67. $tmpHtml = $this->pageNumList[0] >= 2 ? '...' : '';
  68. $pageHtml .= $tmpHtml;
  69. // 页码
  70. foreach ($this->pageNumList as $pageNum) {
  71. $tmpHtml = $pageNum == $this->currentPage ? sprintf('<span class="active">%d</span>', $pageNum)
  72. : sprintf('<a class="pageNum {$pageNum}" href="%s?p=%d&r=%d">%d</a>', $_SERVER['PHP_SELF'], $pageNum, $this->pageSize, $pageNum);
  73. $pageHtml .= $tmpHtml;
  74. }
  75. // 间隔符
  76. $tmpHtml = $this->pageNumList[array_key_last($this->pageNumList)] + 1 <= $this->pageCount ? '...' : '';
  77. $pageHtml .= $tmpHtml;
  78. // 下一页
  79. $tmpHtml = $this->currentPage >= $this->pageCount ? '<span class="pageNum disabled">下一页</span>'
  80. : sprintf('<a class="pageNum" href="%s?p=%d&r=%d">下一页</a>', $_SERVER['PHP_SELF'], $this->currentPage + 1, $this->pageSize);
  81. $pageHtml .= $tmpHtml;
  82. // 末页
  83. $tmpHtml = $this->currentPage >= $this->pageCount ? '<span class="pageNum disabled">末页</span>'
  84. : sprintf('<a class="pageNum" href="%s?p=%d&r=%d">末页</a>', $_SERVER['PHP_SELF'], $this->pageCount, $this->pageSize);
  85. $pageHtml .= $tmpHtml;
  86. // 总页码
  87. $pageHtml .= "<span>共{$this->pageCount}页</span>";
  88. // 页码跳转表单
  89. $tmpHtml = "<form action='{$_SERVER['PHP_SELF']}' method='get'> <input type='text' name='p'><input type='hidden' name='r' value='{$this->pageSize}'><button type='submit'>跳转</button></form>";
  90. $pageHtml .= $tmpHtml;
  91. $pageHtml .= '</div>';
  92. return $pageHtml;
  93. }
  94. // 直接向浏览器输出分页信息
  95. public function echoPagination()
  96. {
  97. echo $this->getPagination();
  98. }
  99. }

3.查询球员分页信息脚本player.php

  1. <?php
  2. require('../out.php');
  3. require('connect.php');
  4. // 查询记录总数
  5. $sql = 'SELECT count(`id`) as row_count FROM `player`';
  6. $count = ($pdo->query($sql)->fetch(PDO::FETCH_NUM))[0] ?? 0;
  7. // 单页球员数量
  8. $rowPerPage = ($_GET['r'] && !empty($_GET['r'])) ? $_GET['r'] : 3;
  9. $rowPerPage = filter_var($rowPerPage, FILTER_VALIDATE_INT) ? $rowPerPage : 3;
  10. // 当前页
  11. $currentPage = ($_GET['p'] && !empty($_GET['p'])) ? $_GET['p'] : 1;
  12. $currentPage = filter_var($currentPage, FILTER_VALIDATE_INT, ['option' => []]) ? $currentPage : 1;
  13. $currentPage = $currentPage < 1 ? 1 : ($currentPage > ceil(floatval($count) / $rowPerPage) ? ceil(floatval($count) / $rowPerPage) : $currentPage);
  14. // 查询页面数据
  15. $start = ($currentPage - 1) * $rowPerPage;
  16. $sql = "SELECT * FROM `player` LIMIT {$start}, {$rowPerPage}";
  17. $players = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
  18. // 加载显示列表数据的模板
  19. require('player_list.php');

4. 球员信息列表player_list.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>球员列表</title>
  7. <style>
  8. @import 'style/page_style.css';
  9. @import 'style/page_style.css';
  10. @import 'style/list.css';
  11. </style>
  12. </head>
  13. <?php
  14. require('pagination.php');
  15. ?>
  16. <body>
  17. <table cellspacing="0" align="center">
  18. <caption>球员列表</caption>
  19. <thead>
  20. <tr>
  21. <th>ID</th>
  22. <th>姓名</th>
  23. <th>球队</th>
  24. <th>身高(cm)</th>
  25. <th>体重(kg)</th>
  26. <th>位置</th>
  27. <th>创建时间</th>
  28. <th>修改时间</th>
  29. <th>操作</th>
  30. </tr>
  31. </thead>
  32. <tbody>
  33. <?php if (!empty($players) && count($players) > 0) : ?>
  34. <?php foreach ($players as $player) : ?>
  35. <tr>
  36. <td><?php echo $player['id']; ?></td>
  37. <td><?php echo $player['name']; ?></td>
  38. <td><?php echo $player['team']; ?></td>
  39. <td><?php echo $player['height']; ?></td>
  40. <td><?php echo $player['weight']; ?></td>
  41. <td><?php echo $player['position']; ?></td>
  42. <td><?php echo date('Y-m-d H:i:s', $player['create_time']); ?></td>
  43. <td><?php echo date('Y-m-d H:i:s', $player['update_time']); ?></td>
  44. <td>
  45. <a href="edit_player.php?id=<?php echo $player['id']; ?>&pos=<?php echo urlencode($_SERVER['QUERY_STRING']); ?>">修改</a>
  46. <a href="del_player.php?id=<?php echo $player['id']; ?>&name=<?php echo $player['name']; ?>&pos=<?php echo urlencode($_SERVER['QUERY_STRING']); ?>">删除</a>
  47. </td>
  48. </tr>
  49. <?php endforeach; ?>
  50. <?php else : ?>
  51. <tr>
  52. <td colspan="9">啥也没查到...</td>
  53. </tr>
  54. <?php endif ?>
  55. </tbody>
  56. </table>
  57. <?php (new Pagination($count, $currentPage, $rowPerPage, 5))->echoPagination();
  58. ?>
  59. <?php //echo (new Pagination($count, $currentPage, 3, 5));
  60. ?>
  61. </body>
  62. </html>

5. 处理更新的脚本do_update.php

  1. <?php
  2. require_once('connect.php');
  3. require_once('../out.php');
  4. $sql = "UPDATE `player` SET `name` = :name, `team` = :team, `height` = :height, `weight` = :weight, `position` = :position, `update_time` = :update_time WHERE `id` = :id";
  5. $param = $_POST;
  6. $param['update_time'] = time();
  7. $pos = $param['pos'];
  8. unset($param['pos']);
  9. $stmt = $pdo->prepare($sql);
  10. $stmt->execute($param);
  11. if ($stmt->rowCount() === 1) {
  12. if (empty($pos))
  13. echo ("<script>alert('修改成功');window.history.back();</script>");
  14. else {
  15. $pos = urldecode($pos);
  16. echo ("<script>alert('修改成功');window.location='/0512/player.php?{$pos}';</script>");
  17. }
  18. } else {
  19. echo ("<script>alert('修改失败');</script>");
  20. }

6. 更新球员信息界面edit_player.php

  1. <?php
  2. require 'connect.php';
  3. require('../out.php');
  4. $id = $_GET['id'];
  5. if (empty($id) || !filter_var($id, FILTER_VALIDATE_INT, ['options' => ['min-range' => 1]])) {
  6. echo ("<script>alert('无效的ID值!');window.history.go(-1);</script>");
  7. die;
  8. }
  9. $sql = "SELECT * FROM `player` WHERE `id` = ?";
  10. $stmt = $pdo->prepare($sql);
  11. $stmt->execute([$id]);
  12. if ($stmt->rowCount() !== 1) {
  13. echo ("<script>alert('无效的ID值');window.history.go(-1);</script>");
  14. die;
  15. }
  16. $player = $stmt->fetch(PDO::FETCH_ASSOC);
  17. ?>
  18. <!DOCTYPE html>
  19. <html lang="en">
  20. <head>
  21. <meta charset="UTF-8">
  22. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  23. <title>修改球员信息</title>
  24. <style>
  25. @import url('style/common.css');
  26. @import url('style/edit.css');
  27. </style>
  28. </head>
  29. <body>
  30. <section>
  31. <div class="player-edit-header">修改球员信息</div>
  32. <div class="player-info">
  33. <form action="do_update.php" method="post">
  34. <input type="hidden" name="id" value="<?php echo $player['id']; ?>">
  35. <input type="hidden" name="pos" value="<?php echo $_GET['pos']; ?>">
  36. <div class="info-item">
  37. <label for="name">姓名: </label>
  38. <input type="text" name="name" id="name" value="<?php echo $player['name']; ?>" required autofocus>
  39. </div>
  40. <div class="info-item">
  41. <label for="team">球队: </label>
  42. <input type="text" name="team" id="team" value="<?php echo $player['team']; ?>" required>
  43. </div>
  44. <div class="info-item">
  45. <label for="height">身高(cm): </label>
  46. <input type="number" name="height" id="height" value="<?php echo $player['height']; ?>" required>
  47. </div>
  48. <div class="info-item">
  49. <label for="weight">体重(kg): </label>
  50. <input type="number" name="weight" id="weight" value="<?php echo $player['weight']; ?>" required>
  51. </div>
  52. <div class="info-item">
  53. <label for="position">位置: </label>
  54. <input type="text" name="position" id="position" value="<?php echo $player['position']; ?>" required>
  55. </div>
  56. <div class="info-item">
  57. <button type="submit">保存</button>
  58. </div>
  59. </div>
  60. </form>
  61. </section>
  62. </body>
  63. </html>

7. 执行删除球员的脚本do_del.php

  1. <?php
  2. require_once('../out.php');
  3. // 球员id
  4. $id = filter_var($_GET['id'], FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]);
  5. // 球员列表的分页参数
  6. $pos = !empty($_GET['pos']) ? '?' . urldecode($_GET['pos']) : '';
  7. // 无效的id,不处理
  8. if(!$id) {
  9. echobr("<script>alert('无效的参数');window.location.href='/0512/player.php{$pos}'</script>");
  10. }
  11. require('connect.php');
  12. $sql = "DELETE FROM `player` WHERE `id` = :id";
  13. $stmt = $pdo->prepare($sql);
  14. $stmt->execute(['id' => $id]);
  15. // 判断处理条数
  16. if ($stmt->rowCount() === 1) {
  17. echobr("<script>alert('删除成功');window.location.href='/0512/player.php{$pos}'</script>");
  18. } else {
  19. echobr("更新失败");
  20. printfpre($stmt->errorInfo());
  21. echobr("<a href='/0512/player.php{$pos}'>返回</a>");
  22. }
  23. ?>

8. 询问是否删除球员的页面del_player.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>确认删除</title>
  7. <style>
  8. @import url('style/common.css');
  9. @import url('style/del.css');
  10. </style>
  11. </head>
  12. <body>
  13. <section>
  14. <span>确认要删除<strong><?php echo $_GET['name'] ?></strong>吗?</span>
  15. <a href="/0512/player.php<?php echo $_GET['pos'] ? '?' . $_GET['pos'] : ''; ?>" class="btn">取 消</a>
  16. <a href="do_del.php?id=<?php echo $_GET['id'] ?>&pos=<?php echo urlencode($_GET['pos']) ?>">确 认</a>
  17. </section>
  18. </body>
  19. </html>

运行效果:

    1. 球员列表, 首页, 首页/上一页按钮不能点击

    1. 指定页面记录数为5的球员列表, 中间页码, 激活首页/上一页按钮

    1. 更新球员信息

    1. 删除球员

外部对象的两种注入方式

1. 球员操作类1(基于构造方法的注入方式)PlayerOpera1.php

  1. <?php
  2. namespace di\operate;
  3. use PDO;
  4. // 基于构造方法的注入方式
  5. class PlayerOpera1 {
  6. // PDO实例
  7. private $pdo = null;
  8. public function __construct($pdo)
  9. {
  10. $this->pdo = $pdo;
  11. }
  12. /**
  13. * 查询所有球员信息
  14. */
  15. public function allPlayers() {
  16. return $this->pdo->query("SELECT * FROM `player`")->fetchAll(PDO::FETCH_ASSOC);
  17. }
  18. /**
  19. * 查询某个球员
  20. */
  21. public function player($id) {
  22. if(filter_var($id, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]))
  23. return $this->pdo->query("SELECT * FROM `player` WHERE `id` = {$id}")->fetch(PDO::FETCH_ASSOC);
  24. else {
  25. echo('无效的参数');die;
  26. }
  27. }
  28. }

2. 球员操作类2(基于类方法参数的注入方式)PlayerOpera2.php

  1. <?php
  2. namespace di\operate;
  3. // 基于方法参数的注入方式
  4. use PDO;
  5. class PlayerOpera2 {
  6. public function __construct()
  7. {
  8. }
  9. /**
  10. * 查询所有球员信息
  11. */
  12. public function allPlayers(PDO $pdo) {
  13. return $pdo->query("SELECT * FROM `player`")->fetchAll(PDO::FETCH_ASSOC);
  14. }
  15. /**
  16. * 查询某个球员
  17. */
  18. public function player(int $id, PDO $pdo) {
  19. if(filter_var($id, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]))
  20. return $pdo->query("SELECT * FROM `player` WHERE `id` = {$id}")->fetch(PDO::FETCH_ASSOC);
  21. else {
  22. echo ('无效的参数');die;
  23. }
  24. }
  25. }

3. 客户端操作脚本client.php

  1. <?php
  2. namespace di;
  3. require('../out.php');
  4. require('PlayerOpera1.php');
  5. require('PlayerOpera2.php');
  6. use di\operate\PlayerOpera1;
  7. use di\operate\PlayerOpera2;
  8. // 客户端
  9. require('../0512/connect.php');
  10. // 1. 基于构造方法的注入方式
  11. $playerOpera1 = new PlayerOpera1($pdo);
  12. // 查询出所有球员数据
  13. $players = $playerOpera1->allPlayers();
  14. // printfpre($players);
  15. /* result:
  16. Array
  17. (
  18. [0] => Array
  19. (
  20. [id] => 1
  21. [name] => 勒布朗-詹姆斯
  22. [team] => 湖人
  23. [height] => 203
  24. [weight] => 113
  25. [position] => F-G
  26. [create_time] => 1589387682
  27. [update_time] => 1589477867
  28. )
  29. [1] => Array
  30. (
  31. [id] => 2
  32. [name] => 安东尼-戴维斯
  33. [team] => 湖人
  34. [height] => 208
  35. [weight] => 115
  36. [position] => F-C
  37. [create_time] => 1589387682
  38. [update_time] => 1589387682
  39. )
  40. 略...
  41. */
  42. // 2. 基于方法参数的注入方式
  43. $playerOpera2 = new PlayerOpera2;
  44. // 查询某个球员的信息
  45. $id = 1;
  46. $player = $playerOpera2->player($id, $pdo);
  47. printfpre($player);
  48. /* result:
  49. Array
  50. (
  51. [id] => 1
  52. [name] => 勒布朗-詹姆斯
  53. [team] => 湖人
  54. [height] => 203
  55. [weight] => 113
  56. [position] => F-G
  57. [create_time] => 1589387682
  58. [update_time] => 1589477867
  59. )
  60. */

学习心得

  • 分页的实现, 封装成了一个分页类, 可以在其他地方使用, 慢慢体会到封装类带来的代码复用的遍历.

  • 两种注入方式: 当只需要对类中的某个方法中注入外部对象时, 使用基于方法参数的注入即可. 若类中的多个方法都需要注入某个相同的外部对象, 使用基于方法参数的注入方式, 会使得代码冗余. 此时, 使用基于构造方法的注入方式, 把外部对象通过构造方法注入并设定为类的一个属性值, 这样在用到该外部对象的时候, 直接使用指向该外部对象的类属性即可.

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:看来你对变量过滤器很感兴趣, 这是一个好习惯, 希望保持下去
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post