博客列表 >PHP基础-查询分页/外部对象的两种注入方式

PHP基础-查询分页/外部对象的两种注入方式

岂几岂几
岂几岂几原创
2020年05月18日 00:33:48735浏览

查询分页

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. */

学习心得

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

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

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