博客列表 >简易数据管理案例带有分页展示、新增、删除、修改和服务容器的概念与实际测试

简易数据管理案例带有分页展示、新增、删除、修改和服务容器的概念与实际测试

Tlilam的PHP之路
Tlilam的PHP之路原创
2020年09月16日 21:00:22737浏览

数据管理案例

获取数据页面

pageData.php 获取前端页面的基本数据,加入了一个小判断

  1. <?php
  2. $dsn = 'mysql:host=localhost;dbname=phpedu';
  3. $username = 'root';
  4. $password = 'root';
  5. $db = new PDO($dsn,$username,$password);
  6. // 设置每页的条数
  7. $num = 2;
  8. // 获取页数,P存在使用p,不存在就使用1
  9. $page = $_GET['p']?? 1;
  10. // 获取总页数,结果需要向上取整CEIL 向上取整,count统计记录
  11. $sql = "SELECT CEIL(COUNT(*) / {$num}) AS `pages` FROM `users` ";
  12. $pages = $db->query($sql)->fetch()['pages'];
  13. // 更多安全设置的$page,当页数小于1 都设置为1 当页数超过总页数设为第一页
  14. if($page <= 1){
  15. $page = 1;
  16. }else if($page > $pages){
  17. $page = 1;
  18. }
  19. // 得到偏移量 (p - 1) * n
  20. $offset = ($page - 1) * $num;
  21. $sql = "SELECT `id`,`name`,`email` FROM `users` LIMIT {$offset}, {$num}";
  22. $users = $db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
  23. // print_r($pages);

分页技术

前端页面test3.php这是完整的页面,上部分是分页的逻辑判断,下部分是渲染部分,表格渲染,分页渲染

  1. <?php
  2. //引入分页数据页面
  3. require 'pageData.php';
  4. // 设置$prev上一页和$next下一页的值
  5. if($page > 1){
  6. $prev = $page -1;
  7. }
  8. if($page < $pages){
  9. $next = $page + 1;
  10. }
  11. // 智能分页的设置
  12. //------------------------------------------------------------------
  13. // 显示页码数量 需要是奇数
  14. $showPages = 5;
  15. // 新的起始页码,只是显示的页码 默认给1
  16. $startPage = 1;
  17. // 新的结束页码 默认给总页数
  18. $endPage = $pages;
  19. // 偏移量:当页数变动成新的时候,起始页码是当前页码减去偏移量,结束页码是当前页码加上偏移量
  20. $offsetPage = ($showPages-1) / 2;
  21. // 前提条件 智能分页 需要展示条数小于总页数才显示
  22. if($showPages < $pages){
  23. // 当前页码要高于偏移量加1 就是 例如这里 页码需要大于 3 以上才可以出现,
  24. // 低于3就是在1、2、3页内前面都没有多余页码,显示来干嘛
  25. if($page > $offsetPage+1 ) $startOmit='...';
  26. // 当前页码大于偏移量的时候就要改变起始页码和结束页码了
  27. if($page > $offsetPage){
  28. $startPage = $page-$offsetPage;
  29. $endPage = $page+$offsetPage;
  30. // 判断结束页是否越界,不允许结束页大于总页数的情况
  31. if($endPage > $pages){
  32. $endPage = $pages;
  33. // 当endPage也就是($page+$offsetPage) 大于总页数,就将endPage设置为总页数
  34. // endPage值改变了,startPage也应该改变,不然显示数量就不对了
  35. $startPage = $pages-($showPages-1);
  36. // 解释:起始页码等于 总页数减去(展示页数减一)
  37. // 举例总页数11 展示页码 5 结束页码等于总页数11 起始页码等于11-5=6 下面的循环从6开始 6 7 8 9 10 11这样就会出现6条
  38. // 减1的话就是11-4=7从 7 8 9 10 11 这样才是正确的起始页码,展示5位页码
  39. }
  40. // 如果小于偏移量起始页就是1 结束页就是显示条数的值
  41. }else{
  42. $startPage = 1;
  43. $endPage = $showPages;
  44. }
  45. // 当前页码大于展示页数,并且当前页码加上偏移量还小于总页码(不包含等于)的情况才显示这个
  46. if( $page+$offsetPage < $pages )$endOmit='...';
  47. }
  48. ?>
  49. <!DOCTYPE html>
  50. <html lang="en">
  51. <head>
  52. <meta charset="UTF-8">
  53. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  54. <title>高端智能的分页条</title>
  55. <link rel="stylesheet" href="style.css">
  56. </head>
  57. <body>
  58. <p>
  59. <a href="">用户登录</a>
  60. </p>
  61. <table>
  62. <caption>用户信息表 <button onclick="location.href='handles.php?action=add'">添加</button></caption>
  63. <thead>
  64. <th>ID</th>
  65. <th>姓名</th>
  66. <th>邮箱</th>
  67. <th>操作</th>
  68. </thead>
  69. <tbody>
  70. <?php foreach($users as $user) :?>
  71. <tr>
  72. <td><?=$user['id']?></td>
  73. <td><?=$user['name']?></td>
  74. <td><?=$user['email']?></td>
  75. <td><button onclick="location.href='handles.php?action=edit&id=<?=$user['id']?>'" >编辑</button>
  76. <button onclick="del(<?=$user['id']?>)">删除</button></td>
  77. </tr>
  78. <?php endforeach ?>
  79. </tbody>
  80. </table>
  81. <p>
  82. <!-- 判断显示 在第一页的时候应该没有首页和上一页的按钮 -->
  83. <?php if($page != 1) :?>
  84. <!-- 固定首页 将p对应值设置为1 -->
  85. <a href="<?=$_SERVER['PHP_SELF'].'?p=1'?>">首页</a>
  86. <!-- 显示上一页 -->
  87. <a href="<?=$_SERVER['PHP_SELF'].'?p='.$prev?>">上一页</a>
  88. <!-- 判断是否有值 -->
  89. <?php if(isset($startOmit)) :?>
  90. <a href="#"><?=$startOmit?></a>
  91. <?php endif ?>
  92. <?php endif ?>
  93. <!-- 循环输出页数 -->
  94. <?php for($i=$startPage; $i<=$endPage; $i++) : ?>
  95. <!-- 当$i等于页码 给class赋值 -->
  96. <?php $active = ($i == $page ) ? 'active' : null; ?>
  97. <a href="<?=$_SERVER['PHP_SELF'].'?p='.$i?>" class="<?=$active?>" ><?=$i?></a>
  98. <?php endfor ?>
  99. <!-- 判断显示 在最后一页的时候应该没有尾页和下一页的按钮 -->
  100. <?php if($page != $pages) :?>
  101. <!-- 判断是否有值 -->
  102. <?php if(isset($endOmit)) :?>
  103. <a href="#"><?=$endOmit?></a>
  104. <?php endif ?>
  105. <!-- 显示下一页 -->
  106. <a href="<?=$_SERVER['PHP_SELF'].'?p='.$next?>">下一页</a>
  107. <!-- 固定尾页 将P对应值设为总页数 -->
  108. <a href="<?=$_SERVER['PHP_SELF'].'?p='.$pages?>">尾页</a>
  109. <?php endif ?>
  110. </p>
  111. </body>
  112. <script>
  113. //确认事件,用户点击确定的时候才跳转URL
  114. function del(id){
  115. let url = 'http://php.edu/0912/handles.php?action=delete&id='+id;
  116. return confirm('是否删除?') ?location.href=url : false;
  117. }
  118. </script>
  119. </html>

在首页不显示上一页和首页,会显示更多按钮…

完全显示全部按钮

在尾页不显示下一页和尾页,会显示更多按钮…

分页总结

  • 计算出符合条件的总页数,CEIL(COUNT(*)) / n,CEIL向上取整,Count统计,*全部或某个字段,n=每页条数
  • 计算偏移量(p-1)*n公式计算,p=页码从1开始,n=每页条数
  • 前端循环出全部页码或部分页码,改变URL中p=页码数,改变显示数据。http://php.edu/0912/test3.php?p=1
  • 基本概念如上,自己可以在此基础上优化,例如案例中固定5位变化显示页码,上下页,首尾页等

其他操作代码,更新,插入,删除

handles.php操作分发器

  1. <?php
  2. // 1.进行数据库连接
  3. $dsn ='mysql:host=localhost;dbname=phpedu';
  4. $username = 'root';
  5. $password = 'root';
  6. $db = new PDO($dsn,$username,$password);
  7. // 2.获取操作类型和id
  8. $action = $_GET['action'];
  9. $id = $_GET['id'];
  10. // 3.操作分发器
  11. switch($action){
  12. case 'edit':
  13. // 3.1引入编辑页码操作
  14. $user = $db->query('SELECT * FROM `users` WHERE id ='.$id)->fetch(PDO::FETCH_ASSOC);
  15. include 'edit.php';
  16. break;
  17. case 'save':
  18. // 3.2保存数据操作
  19. // print_r($_POST);
  20. $sql = 'UPDATE `users` SET `name`=?, `email`=? WHERE `id`=?;';
  21. $stmt = $db->prepare($sql);
  22. if(!empty($_POST)){
  23. $stmt->execute([$_POST['name'], $_POST['email'], $id]);
  24. if($stmt->rowCount()==1){
  25. echo '<script>alert("更新成功");location.href="test3.php";</script>';
  26. }else{
  27. echo "<script>alert('没有数据被更新,请检查内容是否被修改');location.href='test3.php'</script>";
  28. }
  29. }
  30. break;
  31. case 'add':
  32. // 3.3引入新增用户操作
  33. include 'add.php';
  34. break;
  35. case 'saveAdd':
  36. // 3.4 保存新用户数据
  37. // print_r($_POST);
  38. // 可以进行更多的安全判断,和使用数据过滤器
  39. if(empty($_POST['email'])){
  40. echo "<script>alert('请输入邮箱!');location.href='test3.php'</script>";
  41. }
  42. // 实际操作
  43. $sql = 'INSERT INTO `users` SET `name`=?, `email`=? ,`password`=?;';
  44. $stmt = $db->prepare($sql);
  45. $stmt->execute([$_POST['name'], $_POST['email'], sha1($_POST['password'])]);
  46. if($stmt->rowCount()==1){
  47. echo '<script>alert("添加成功");location.href="test3.php";</script>';
  48. }else{
  49. echo "<script>alert('添加失败');location.href='test3.php'</script>";
  50. }
  51. break;
  52. case 'delete':
  53. // 3.5删除操作
  54. $stmt = $db->prepare('DELETE FROM `users` WHERE id=?;');
  55. $stmt->execute([$id]);
  56. if($stmt->rowCount() == 1){
  57. echo '<script>alert("删除成功");location.href="test3.php";</script>';
  58. }
  59. break;
  60. default:
  61. // 默认操作,直接打开此页面跳转回数据页
  62. echo '<script>alert("非法操作");location.href="test3.php";</script>';
  63. }

add.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. </head>
  8. <body>
  9. <form action="<?= $_SERVER['PHP_SELF'].'?action=saveAdd'?>" method="POST" >
  10. <fieldset>
  11. <legend>用户添加</legend>
  12. <p>
  13. <label for="">用户名:</label>
  14. <input type="text" name="name" id="name" >
  15. </p>
  16. <p>
  17. <label for="">邮箱:</label>
  18. <input type="email" name="email" id="email" >
  19. </p>
  20. <p>
  21. <label for="">密码:</label>
  22. <input type="password" name="password" id="password" >
  23. </p>
  24. <p>
  25. <input type="submit" value="提交">
  26. </p>
  27. </fieldset>
  28. </form>
  29. </body>
  30. </html>

edit.php修改页面

  1. <?php
  2. // 编辑表单
  3. // http://php.edu/0912/handle.php?action=edit&id=13
  4. // 从上面的url中解析出id,根据id查询获取对应的用户数据
  5. $user = $pdo->query('select * from users where id='.$id)->fetch();
  6. // print_r($user);
  7. ?>
  8. <!DOCTYPE html>
  9. <html lang="en">
  10. <head>
  11. <meta charset="UTF-8">
  12. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  13. <title>用户编辑</title>
  14. </head>
  15. <body>
  16. <h3>用户编辑</h3>
  17. <form action="<?php echo $_SERVER['PHP_SELF']. '?action=doedit&id='.$id?>" method="post">
  18. <p>
  19. <label for="name">用户名:</label>
  20. <input type="text" id="name" name='name' value="<?=$user['name']?>">
  21. </p>
  22. <p>
  23. <label for="email">邮箱:</label>
  24. <input type="email" name='email' id="email" value="<?=$user['email']?>">
  25. </p>
  26. <p>
  27. <button>保存</button>
  28. </p>
  29. </form>
  30. </body>
  31. </html>

服务容器

Model.php数据获取类

  1. <?php
  2. namespace mvc_test;
  3. // 当声明了命名空间,不进行USE或者是\表示清楚PDO,它就会去找命名空间下的PDO这样是会找不到的
  4. use PDO;
  5. class Model{
  6. public function getData(){
  7. return
  8. (new PDO('mysql:host=localhost;dbname=phpedu','root','root'))
  9. ->query('SELECT id,name,email from users limit 5')
  10. ->fetchAll(PDO::FETCH_ASSOC);
  11. }
  12. }

View.php视图渲染类

  1. <?php
  2. // 视图类
  3. namespace mvc_demo;
  4. class View
  5. {
  6. // 展示模型中的数据
  7. public function fetch($data)
  8. {
  9. $table = '<table>';
  10. $table .= '<caption>用户信息表</caption>';
  11. $table .= '<tr><th>ID</th><th>姓名</th><th>邮箱</th></tr>';
  12. // 遍历用户数据
  13. foreach ($data as $user) {
  14. $table .= '<tr>';
  15. $table .= '<td>'.$user['id'].'</td>';
  16. $table .= '<td>'.$user['name'].'</td>';
  17. $table .= '<td>'.$user['email'].'</td>';
  18. $table .='</tr>';
  19. }
  20. $table .= '</table>';
  21. return $table;
  22. }
  23. }
  24. echo '<style>
  25. table {border-collapse: collapse; border: 1px solid;text-align: center; width: 500px;height: 150px;width: 600px;}
  26. caption {font-size: 1.2rem; margin-bottom: 10px;}
  27. tr:first-of-type { background-color:coral;}
  28. td,th {border: 1px solid; padding:5px}
  29. </style>';

Controller.php控制器页面

  1. <?php
  2. namespace mvc_test;
  3. use closure;
  4. // 匿名函数类。
  5. require __DIR__.DIRECTORY_SEPARATOR.'Model.php';
  6. require __DIR__.DIRECTORY_SEPARATOR.'View.php';
  7. //----------------------------------------------------------------
  8. // 服务容器
  9. class Container{
  10. // 1.对象容器,数组可以存储各种数据包括类实例
  11. protected $instances = [];
  12. // 2.实例绑定到容器中,
  13. // 参数1:对象别名,推荐还是和类名一致
  14. // 参数2:对象, closure声明参数是匿名函数,可以省略
  15. public function bind($alias,closure $process)
  16. {
  17. $this->instances[$alias] = $process;
  18. }
  19. // 3.容器内取出对象(类实例)
  20. public function make($alias,$params=[])
  21. {
  22. // 避免调用影响,使用回调方式去调用
  23. return call_user_func_array($this->instances[$alias],$params);
  24. }
  25. }
  26. // 将依赖的外部对象绑定到服务容器中
  27. $container = new Container();
  28. // 将模型绑定到容器中
  29. $container->bind('model',function(){ return new Model();});
  30. // 将视图绑定到容器中
  31. $container->bind('view',function(){ return new View();});
  32. // print_r($container);die();
  33. //----------------------------------------------------------------
  34. // 控制器
  35. class Controller
  36. {
  37. // 存放服务容器,给其他方式调用
  38. protected $container ='';
  39. // 构造方法,使控制器实例的时候传入服务容器赋值给属性存放
  40. public function __construct(Container $container)
  41. {
  42. $this->container = $container;
  43. }
  44. // 获取数据并展示出来,传入服务容器
  45. public function index()
  46. {
  47. //1. 获取数据
  48. $data = $this->container->make('model')->getData();
  49. // 2. 渲染模板
  50. return $this->container->make('view')->fetch($data);
  51. }
  52. }
  53. // -------------------------------------------------
  54. // 客户端 :测试
  55. // 实例控制器,将服务容器对象作为参数传入
  56. $controller = new Controller($container);
  57. echo $controller->index();

服务容器的总结

  • 简单的服务容器概念
  • 就是将各种模型类,视图类等等的实例化存储到一个类(服务容器)中,这样可以容纳多个类,访问也很简单
  • 控制器创建属性,构造方法存储服务容器,方法需要的时候只需调用这个属性,取出对应的对象进行操作
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议