博客列表 >方法(包括静态方法)拦截器以及事件委托请求委托及通过数据库拿到数据分页的提取以及单文件上传php操作方法

方法(包括静态方法)拦截器以及事件委托请求委托及通过数据库拿到数据分页的提取以及单文件上传php操作方法

卢先生
卢先生原创
2022年02月22日 17:27:11500浏览

方法拦截器+静态方法拦截器

方法拦截器类似属性拦截器,属性拦截器当属性不存在时或者不公开是,调用set跟get方法,set写入 get查询,方法拦截器公开的方法拦截器使用call,在本类中不存在某个方法时,触动方法拦截器,call,或者当本类中静态方法不存在时,触动静态方法拦截器__callstatic来执行操作,方法拦截器传入的值也是方法名称,第二个传入的值是方法的值,值可能为多个,所以是以[数组]的方式存在的。
代码部分:

  1. <?php
  2. // 方法拦截器 方法拦截器类似于属性拦截器,属性拦拦截器是set跟get ,方法拦截器是会调用的是__call __callStatic
  3. /**
  4. * 根据方法拦截器 搞一份事件委托和构造器查询
  5. *
  6. *
  7. */
  8. class User
  9. {
  10. public function normal()
  11. {
  12. return __METHOD__;
  13. }
  14. //当访问不存在的方法时,或不可见的方法时,调用__Call方法
  15. public function __Call($method, $arges) //第一是传进来的是第一个不可见的方法名称, 第二个是数组
  16. {
  17. var_dump($method);
  18. echo '<br>';
  19. var_dump($arges);
  20. echo '<br>';
  21. // echo 111;
  22. printf('调用当前类中不存在的普通方法%s,参数列表为[%s]<br>', $method, implode(',', $arges)); // $arges传进来的是数组,可以通过implode()来分割成字符串,有俩值implode('分割符号',$args分割数组的变量)
  23. }
  24. public static function __callStatic($name, $arguments)
  25. {
  26. printf('目前是静态方法,当前调用的类不存在的静态普通方法%s,参数列表[%s]<br>', $name, implode(',', $arguments));
  27. }
  28. }
  29. $u = new User;
  30. echo $u->normal();
  31. $u->login('老王登录了网站,想偷取数据', '是真的', '他还拿了你的保险箱');
  32. User::ad('点击一下广告', '你就有钱赚', '到账50元');
  33. // $u::ad('点击一下广告', '你就有钱赚', '到账50元');

方法拦截器之事件委托:

方法拦截器事件委托,也是类似属性拦截器的拦截,当工作类,也就是委托方,没有这个方法的时候,将启动事件委托,示例中的代码,是查询数据库的示例,并不是只能在查询数据库中用到,在流程类中,初始化类成员,在被委托方中通过回调call_user_func()的方法,进行对函数的回调,回调到流程类中,通过用户传入的初始值传入到拦截器中,拦截器通过回调函数(因为拦截器收到的是俩参数,一个是拦截的方法名,一个是拦截的方法参数,)传入到拦截器中,通过回调方法,回调到了流程类中,重新赋值执行。

代码部分:

  1. <?php
  2. /**
  3. * 事件委托 请求委托 访问类中不存在的成员方法,会被魔术方法拦截,将请求重定向给别的对象成员方法类处理
  4. *
  5. * 委托是指一个对象转发或者委托一个请求给另外一个对象,被委托的一方替原来的对象处理请求。
  6. * 委托比继承更加灵活 ,父类与子类的关系是固定的,只能单继承,但是请求可以委托给多个对象
  7. */
  8. //被委托的类 数据库查询构造器
  9. class Query
  10. {
  11. // 创建pdo对象的唯一实例
  12. private static $db;
  13. protected $table;
  14. protected $field;
  15. protected $limit;
  16. //private 私有的 阻止此类在外部进行实例化
  17. private function __construct()
  18. {
  19. }
  20. //完成pdo的封装操作 后面进行下一步操作
  21. static function connect($dsn, $user, $pwd)
  22. {
  23. if (is_null(static::$db)) //检测变量是否为 NULL 延迟绑定
  24. {
  25. static::$db = new pdo($dsn, $user, $pwd);
  26. // return static::$db;
  27. }
  28. return new static;
  29. }
  30. public function table($table)
  31. {
  32. $this->table = $table;
  33. return $this;
  34. }
  35. public function field($field)
  36. {
  37. $this->field = $field;
  38. return $this;
  39. }
  40. public function limit($limit)
  41. {
  42. $this->limit = $limit;
  43. return $this;
  44. }
  45. public function getSql()
  46. {
  47. return sprintf('SELECT %s FROM %s LIMIT %d', $this->field, $this->table, $this->limit);
  48. }
  49. public function select()
  50. {
  51. return static::$db->query($this->getSql())->fetchAll(pdo::FETCH_ASSOC);
  52. }
  53. }
  54. //委托方
  55. class Db
  56. {
  57. static function __callStatic($name, $arguments)
  58. {
  59. $dsn = 'mysql:host=localhost;dbname=phpcn;charset=utf8;port=3306';
  60. $user = 'root';
  61. $pwd = '123456';
  62. //获取到被委托的类 Query实例
  63. $q = Query::connect($dsn, $user, $pwd);
  64. return call_user_func([$q, $name], ...$arguments); //call_user_func第一个参数 或者说是方法 是被调用的回调函数,其余参数是回调函数的参数。
  65. // 上面的$name在传入的时候不就是table 参数就是mj_course_cat
  66. }
  67. }
  68. //客户端代码
  69. $res = Db::table('mj_course_cat')->field('cat_id,name')->limit(10)->select();
  70. var_dump($res);

看下面截图吧!!

数据(数据库)分页的提取

分页
1.首先赋值一个变量,值为每页取的数据量
2.通过超全局变量get,获取用户通过get传过来的变量,如果通过get传过来为0,那就默认为1
3.计算数据的偏移量 计算方式 页数-1*条数,比如第一次进来,就是偏移0,第二次偏移8,第三次偏移16,也就是查询的。
4.获取所有数据 将偏移量给数据库,也就是从第几个拿,拿几条
5.计算获取的总条数
6.计算总页数,总共有多少页
分页提取的模型部分,就是php处理文件部分
ceil() 向上取整

  1. <?php
  2. $pdo = new pdo('mysql:host=localhost;charset=utf8;port=3306;dbname=phpcn', 'root', '123456', [PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
  3. //每页取8条数据
  4. $pageSize = 8;
  5. // get是前端用户传过来的操作 默认是1,也就是当前访问的第几页
  6. $page = $_GET['page'] ?? 1;
  7. //计算一个偏移量 offset
  8. $offset = ($page - 1) * $pageSize;
  9. // 获取所有的数据
  10. var_dump($offset);
  11. $sql = "SELECT `cou_id`,`title`,`pic`,`info`,`add_time` FROM `mj_course_lists` ORDER BY `cou_id` DESC LIMIT {$offset},{$pageSize}";
  12. $lists = $pdo->query($sql)->fetchAll();
  13. //获取总条数
  14. $sql1 = "SELECT COUNT(`cou_id`)AS `sum` FROM `mj_course_lists`";
  15. $total = $pdo->query($sql1)->fetch()['sum']; //那一维数组的sum下面的值
  16. var_dump($total);
  17. // ceil()向上取整 计算总页数 也就是总条数除以每页数据
  18. $pages = ceil($total / $pageSize);
  19. var_dump($pages);

视图层部分,也就是前端那部分:

1.前端,通过总条数,fetch数组,然后forech遍历拿到数据,拿到数据,遍历到前台,
2.分页数据,自增一个数据,数据小于总页数,也就是小于$pages的值即可

  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. <link rel="stylesheet" href="/static/css/style.css">
  9. <title>Document</title>
  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. <td>创建时间</td>
  21. <td>操作</td>
  22. </tr>
  23. </thead>
  24. <tbody>
  25. <!-- $lists 是在数据库拿到的遍历结果 在pageData.php中 通过fetchall拿到后用foreach遍历出来 -->
  26. <?php foreach ($lists as $list) : ?>
  27. <tr>
  28. <!-- 一维数组 拿结果 -->
  29. <td><?= $list['cou_id'] ?></td>
  30. <td><?= $list['title'] ?></td>
  31. <td><img style="width:100px" src=" <?= $list['pic'] ?>" alt="课程封面"></td>
  32. <td><?= $list['info'] ?></td>
  33. <!-- date(format,timestamp); -->
  34. <!-- 返回将整数 timestamp 按照给定的格式字串而产生的字符串。如果没有给出时间戳则使用本地当前时间。换句话说,timestamp 是可选的,默认值为 time()。 -->
  35. <td><?= date("Y-m-d H:m:s", $list['add_time']) ?></td>
  36. <td><button>删除</button><button>编辑</button></td>
  37. </tr>
  38. <?php endforeach; ?>
  39. </tbody>
  40. </table>
  41. <!-- 生成分页条 -->
  42. <p>
  43. <? for ($i = 1; $i <= $pages; $i++) : ?>
  44. <!-- 通过for里面的i生成页数 赋值给jump也就是当前的页数和后面 2 3 4 5等页数 -->
  45. <? $jump = sprintf('?page=%d', $i) ?>
  46. <!-- 当i=page也就是用户传过来的参数时,将active赋值给$active,如果不是就为空 拿到了当前页面class -->
  47. <? $active = ($i == $page) ? 'active' : '' ?>
  48. <a class="<?= $active ?>" href="<?= $jump ?>"><?= $i ?></a>
  49. <!-- 生成高亮分页条 -->
  50. <? endfor ?>
  51. </p>
  52. </body>
  53. </html>

文件上传

文件上传

1. php 关于文件上传的配置

文件上传项目项在php.ini中设置,常用的配置项有:

序号 配置项 默认值 描述
1 file_uploads On 使 PHP 支持文件上传
2 upload_tmp_dir /tmp 设置上传文件的暂存区位置
3 max_file_uploads 20 单次请求时允许上传的最大文件数量
4 max_execution_time 30 设置脚本被解析器终止之前PHP最长执行时间(秒) ,防止服务器资源被耗尽
5 max_input_time 60 设置 PHP 通过 POST/GET/PUT 解析接收数据的时长(秒)
6 memory_limit 128M 设置脚本能够分配的最大内存容量 单位字节 1M等于1024K,一兆等于1048576字节
7 post_max_size 8M 设置通过 POST方法提交的数据量上限
8 upload_max_filesize 2M 设置上传的单个文件的数据量上限

memory_limit >= post_max_size 防止失控的脚本独占服务器内存,严重时使服务器崩溃
post_max_size > upload_max_filesize 因为后者只是限制通过file输入类型传递过来的数据量,不像post_max_size可以限制所有通过post方法上传的数据量上限

2. $_FILE

  • 上传文件的描述信息,全部保存在系统全局变量$_FILES
  • $_FILES以二维数组形式保存: $_FILES['form_file_name']['key']
  • 'form_file_name': 对应着表单中<input type="file" name="my_pic">name属性值
  • 'key': 共有 5 个键名, 描述如下:
序号 键名 描述
1 name 文件在客户端的原始文件名(即存在用户电脑上的文件名)
2 type 文件的 MIME 类型, 由浏览器提供, PHP 并不检查它
3 tmp_name 文件被上传到服务器上之后,在临时目录中显示的临时文件名
4 error 和该文件上传相关的错误代码
5 size 已上传文件在客户端机器上的实际大小(单位为字节)
  • 文件上传错误信息描述
序号 常量 描述
1 UPLOAD_ERR_OK 0 没有错误发生,文件上传成功
2 UPLOAD_ERR_INI_SIZE 1 文件超过php.iniupload_max_filesize
3 UPLOAD_ERR_FORM_SIZE 2 文件大小超过表单中MAX_FILE_SIZE指定的值
4 UPLOAD_ERR_PARTIAL 3 文件只有部分被上传
5 UPLOAD_ERR_NO_FILE 4 没有文件被上传
6 UPLOAD_ERR_NO_TMP_DIR 6 找不到临时文件夹
7 UPLOAD_ERR_CANT_WRITE 7 文件写入失败

3. PHP文件上传函数

  • 系统中提供了多个文件处理函数,php还提供了两个专门来处理文件上传功能的函数
序号 键名 描述
1 is_uploaded_file() 用来检测文件是否是通过http post方法上传的,而不是系统上的一个文件。作用是防止潜在攻击者通过问题脚本访问并非用于交互的文件
2 move_uploaded_file() 将上传的文件从临时目录移动到最终位置

php单文件上传前端文件

前端文件需要注意的是enctype()函数的值,需要改成multipart/form-data,二进制上传

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  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. </head>
  9. <body>
  10. <!-- 当上传文件时 enctype值需要设置为multipart/form-data,文件时二进制 -->
  11. <form action="doUpload.php" method="post" enctype="multipart/form-data">
  12. <label for="avatar">头像</label>
  13. <input type="file" name="avatar" id="avatar">
  14. <button>文件上传提交</button>
  15. </form>
  16. </body>
  17. </html>

php后端接收文件
php后端接收文件用超全局函数$_FILES来接收前端发过来的参数值
下面使用中的函数及说明

函数名 函数用法 函数解释
explode() explode(‘分割符号’, 接收的文件名) 第一个是分割的符号,第二个是接收的文件名,接收的值是一个数组
end() end(接收的数组) end($arr);如果数组内有多个值,将拿到数组的尾部最后一个值
array_shift() array_shift(接收的数组) array_shift($arr)跟上面的类似,只不过如果数组内有多个值,将拿到数组的头部第一个值
in_array() in_array($ext, $exts) in_array($ext, $exts),第一个参数是检查的类型,第二个是存在数组中存在的类型,检查接收的类型,是不是数组中存在的类型,如果不是,就返回一个错误
move_uploaded_file() move_uploaded_file($tmp_name, $des); move_uploaded_file($tmp_name, $des);第一个参数是需要处理的文件,也就是需要移动的文件,第二个参数是移动到的路径,移动到某个路径
date() date(‘YmdHms’, time()) date(‘YmdHms’, time())第一个是需要转换成的显示的格式,第二个是拿到的时间格式
  1. <?php
  2. //获取文件信息$__file
  3. var_dump($_FILES);
  4. $originalFilename = $_FILES['avatar']['name'];
  5. $type = $_FILES['avatar']['type'];
  6. $tmp_name = $_FILES['avatar']['tmp_name'];
  7. $error = $_FILES['avatar']['error'];
  8. $size = $_FILES['avatar']['size'];
  9. var_dump($error);
  10. switch ($error):
  11. case 0:
  12. echo '<p style="color:green">文件上传成功</p> ';
  13. break;
  14. case 1:
  15. echo '<p style="color:red">文件超过`php.ini`中`upload_max_filesize`值</p>';
  16. break;
  17. case 2:
  18. echo '<p style="color:red">文件大小超过表单中`MAX_FILE_SIZE`指定的值</p>';
  19. break;
  20. case 3:
  21. echo '<p style="color:red">文件只有部分被上传</p>';
  22. break;
  23. case 4:
  24. echo '<p style="color:red">没有文件被上传</p>';
  25. break;
  26. case 6:
  27. echo '<p style="color:red">找不到临时文件夹</p>';
  28. break;
  29. case 6:
  30. echo '<p style="color:red">文件写入失败</p>';
  31. break;
  32. default:
  33. echo '<p style="color:red">系统错误</p>';
  34. break;
  35. endswitch;
  36. // 检查文件格式
  37. // explode()分割成数组,前面是分割的符号,后面是分割的文件名
  38. $arr = explode('.', $originalFilename);
  39. // end()拿到数组的尾部,也就是数组的最后一个 .就没了
  40. $ext = end($arr);
  41. //array_shift拿到数组的第一个 .就没了
  42. $prefix = array_shift($arr);
  43. $exts = ['png', 'jpg', 'jpeg', 'wbmp', 'gif'];
  44. // in_array($ext, $exts) $ext 传过来的文件分割的尾部类型, $exts 数组内存在的类型
  45. if (!in_array($ext, $exts)) {
  46. return '非法文件类型';
  47. }
  48. // 检查大小
  49. // `is_uploaded_file()` | 用来检测文件是否是通过http post方法上传的,而不是系统上的一个文件。作用是防止潜在攻击者通过问题脚本访问并非用于交互的文件
  50. if ($error = 0) {
  51. //移动暂存区的图片到服务器指定的文件目录
  52. // 定义一个要移动的目录
  53. $des = 'storage/';
  54. // file_exists检查是否有这个路径文件 没有就创建一个
  55. if (!file_exists($des)) {
  56. mkdir($des, 0777, true);
  57. }
  58. $newName = date('YmdHms', time()) . md5($prefix) . '.' . $ext;
  59. // move_uploaded_file(暂存区,目的地)
  60. move_uploaded_file($tmp_name, $des);
  61. }
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议