1. 写一个实现的多文件上传案例,并将它封装成一个可复用的函数或类 2. 实例演示MVC与依赖注入的原理,以及服务容器对依赖对象的管理的实现过程。。。。

1. 多文件上传案例

文件夹结构

  • upload.php
  • common.php
  • uploads

uplaod.php

  1. <?php
  2. printf('<pre>%s</pre>', print_r($_FILES, true));
  3. if (count($_FILES) > 0) {
  4. include './common.php';
  5. switch ($_GET['t']) {
  6. case 'alone':
  7. echo upload($_FILES['file']);
  8. break;
  9. case 'onebyone':
  10. foreach ($_FILES as $file) {
  11. // echo $file['name'];
  12. echo upload($file);
  13. }
  14. break;
  15. case 'multipart':
  16. $files = [];
  17. foreach ($_FILES['file']['error'] as $key => $value) {
  18. $files[] = [
  19. 'name' => $_FILES['file']['name'][$key],
  20. 'type' => $_FILES['file']['type'][$key],
  21. 'tmp_name' => $_FILES['file']['tmp_name'][$key],
  22. 'error' => $_FILES['file']['error'][$key],
  23. 'size' => $_FILES['file']['size'][$key],
  24. ];
  25. }
  26. foreach ($files as $file) {
  27. // echo $file['name'];
  28. echo upload($file);
  29. }
  30. // var_dump($files);
  31. break;
  32. default:
  33. echo '未知错误';
  34. }
  35. }
  36. ?>
  37. <!DOCTYPE html>
  38. <html lang="en">
  39. <head>
  40. <meta charset="UTF-8">
  41. <title>图片上传</title>
  42. <style>
  43. form {
  44. width: 20em;
  45. margin: 1em auto;
  46. }
  47. fieldset {
  48. margin: 1em;
  49. display: grid;
  50. place-content: flex-start;
  51. }
  52. button[type=button] {
  53. margin-bottom: .5em;
  54. }
  55. </style>
  56. </head>
  57. <body>
  58. <form action="upload.php?t=alone" method="post" enctype="multipart/form-data">
  59. <fieldset>
  60. <label>单文件上传</label>
  61. <input type="hidden" name="MAX_FILE_SIZE" value="10485760">
  62. <input type="file" name="file">
  63. <button>upload</button>
  64. </fieldset>
  65. </form>
  66. <form action="upload.php?t=onebyone" method="post" enctype="multipart/form-data">
  67. <fieldset>
  68. <label>多文件上传: 逐个上传</label>
  69. <input type="hidden" name="MAX_FILE_SIZE" value="10485760">
  70. <input type="file" name="file1">
  71. <button type="button" onclick="oneByOne()">继续添加文件</button>
  72. <button>upload</button>
  73. </fieldset>
  74. </form>
  75. <form action="upload.php?t=multipart" method="post" enctype="multipart/form-data">
  76. <fieldset>
  77. <label>多文件上传: 一次性上传</label>
  78. <input type="hidden" name="MAX_FILE_SIZE" value="10485760">
  79. <input type="file" name="file[]" multiple>
  80. <button>upload</button>
  81. </fieldset>
  82. </form>
  83. <script>
  84. let oneByOneFileNameIndex = 1;
  85. // 动态添加逐个上传的input
  86. function oneByOne() {
  87. const dom = document.querySelector(`input[name=file${oneByOneFileNameIndex}]`);
  88. const input = document.createElement('input');
  89. input.type = 'file'
  90. input.name = 'file' + ++oneByOneFileNameIndex;
  91. dom.insertAdjacentElement('afterend', input);
  92. }
  93. </script>
  94. </body>
  95. </html>

common.php

  1. <?php
  2. /**
  3. * 文件上传
  4. *
  5. * @param array $files: 一个文件的所有数据
  6. * @return string
  7. */
  8. function upload(array $files): string
  9. {
  10. // 获取文件名
  11. $name = $files['name'];
  12. // 获取临时文件的路径
  13. $tmpName = $files['tmp_name'];
  14. // 获取错误信息
  15. $error = $files['error'];
  16. if ($error === 0) {
  17. // 获取文件类型
  18. $type = strstr($files['type'], '/', true);
  19. // 获取文件后缀
  20. $ext = '.' . strtolower(pathinfo($files['name'], PATHINFO_EXTENSION));
  21. if ($type === 'image') {
  22. $path = "uploads/" . md5($name . date('Ymd') . str_pad(mt_rand(1, 9999), 5, '0', STR_PAD_LEFT)) . $ext;
  23. // 检测临时文件的合法性
  24. if (is_uploaded_file($tmpName)) {
  25. // 移动文件
  26. if (move_uploaded_file($tmpName, $path)) {
  27. // 返回成功
  28. return "<span><p style=\"color:green\">{$name}上传成功</p><img src='{$path}' width=250 alt='{$name}' /></span>";
  29. } else {
  30. return '移动文件失败';
  31. }
  32. } else {
  33. return '临时文件不合法';
  34. }
  35. } else {
  36. return '上传类型错误';
  37. }
  38. } else {
  39. return upload_error($error);
  40. }
  41. }
  42. /**
  43. * 文件上传的错误信息集合
  44. *
  45. * @param int $errno: error代码
  46. * @return string
  47. */
  48. function upload_error(int $errno): string
  49. {
  50. switch ($errno) {
  51. case 1:
  52. $msg = '超过的单文件大小';
  53. break;
  54. case 2:
  55. $msg = '超过前端表单限制';
  56. break;
  57. case 3:
  58. $msg = '上传文件不完整';
  59. break;
  60. case 4:
  61. $msg = '没有文件被上传';
  62. break;
  63. case 6:
  64. $msg = '找不到临时目录';
  65. break;
  66. case 7:
  67. $msg = '写入失败,目标目录无写入权限';
  68. break;
  69. default:
  70. exit('未定义错误');
  71. }
  72. return $msg;
  73. }

2.

  1. MVC:
  2. M-模型(数据库相关的操作),
  3. V-视图(页面,html),
  4. C-控制器(功能:1.获取数据 2.选择视图)
  5. 依赖注入: 简单那来说就是为了解决对象之间的耦合(`在一个类中调用其他类的实例`),例2.1:
  6. 方法: 在类的外部实例化其他类, 然后以参数的方式传入.例:2.2:
  7. 服务容器: 将外部依赖(需要引用的外部类实例)进行统一的管理.例2.3

2.1

  1. <?php
  2. namespace test;
  3. require './Model.php';
  4. require './View.php';
  5. // 服务容器
  6. class Conn
  7. // 控制器
  8. class Controller
  9. {
  10. public function index(): string
  11. {
  12. return (new View())->fetch((new \test\Model())->select()['data']);
  13. }
  14. }

2.2

  1. <?php
  2. namespace test;
  3. require './Model.php';
  4. require './View.php';
  5. // 控制器
  6. class Controller
  7. {
  8. // public function index(): string
  9. // {
  10. // return (new View())->fetch((new \test\Model())->select()['data']);
  11. // }
  12. protected $model;
  13. protected $view;
  14. public function __construct($model,$view) {
  15. $this->model = $model;
  16. $this->view = $view;
  17. }
  18. public function index(): string
  19. {
  20. return $this->view->fetch($this->model->select()['data']);
  21. }
  22. }
  23. $model = new Model();
  24. $view = new View();
  25. $controller = new Controller($model, $view);
  26. echo $controller->index();

2.3

  1. <?php
  2. namespace test;
  3. require './Model.php';
  4. require './View.php';
  5. // 服务容器
  6. class Container
  7. {
  8. // 对象容器
  9. protected $instanles = [];
  10. // 写入对象
  11. public function bind($alias, \Closure $process)
  12. {
  13. $this->instanles[$alias] = $process;;
  14. }
  15. // 取出对象
  16. public function make($alias, $params = [])
  17. {
  18. return call_user_func_array($this->instanles[$alias], $params);
  19. }
  20. }
  21. // 控制器
  22. class Controller
  23. {
  24. /*服务容器*/
  25. public function index(Container $instanles)
  26. {
  27. return $instanles->make('view')->fetch($instanles->make('model')->select()['data']);
  28. }
  29. }

3. MVC简单案例(数据来源: https://www.php.cn/blog/detail/26509.html)

文件夹结构

  • Model.php
  • View.php
  • Controller.php
  • index.php

Model.php

  1. <?php
  2. namespace mvc_demo;
  3. use PDO;
  4. // 模型类
  5. class Model
  6. {
  7. // 获取数据
  8. public function getData()
  9. {
  10. $pdo = new PDO('mysql:dbname=phpedu', 'root', 'root');
  11. $stmt = $pdo->prepare('select * from staffs limit 10');
  12. $stmt->execute();
  13. return $stmt->fetchAll(PDO::FETCH_ASSOC);
  14. }
  15. }

View.php

  1. <?php
  2. namespace mvc_demo;
  3. // 视图
  4. class View
  5. {
  6. // 数据展示
  7. public function fetch($data)
  8. {
  9. $table = '<table border="1" cellspacing="0">';
  10. $table .= '<caption>员工信息表</caption>
  11. <tr bgcolor="lightcyan">
  12. <th>id</th>
  13. <td>姓名</td>
  14. <td>性别</td>
  15. <td>工资</td>
  16. <td>邮箱</td>
  17. <td>生日</td>
  18. </tr>';
  19. foreach ($data as $staff) {
  20. $table .= '<tr>';
  21. $table .= '<td>' . $staff['sid'] . '</td>';
  22. $table .= '<td>' . $staff['name'] . '</td>';
  23. $table .= '<td>' . $staff['gender'] . '</td>';
  24. $table .= '<td>' . $staff['salary'] . '</td>';
  25. $table .= '<td>' . $staff['email'] . '</td>';
  26. $table .= '<td>' . $staff['birthday'] . '</td>';
  27. $table .= '</tr>';
  28. }
  29. $table .= '</table>';
  30. return $table;
  31. }
  32. }

Controller.php

  1. <?php
  2. namespace test;
  3. require './Model.php';
  4. require './View.php';
  5. // 服务容器
  6. class Container
  7. {
  8. // 对象容器
  9. protected $instanles = [];
  10. // 写入对象
  11. public function bind($alias, \Closure $process)
  12. {
  13. $this->instanles[$alias] = $process;;
  14. }
  15. // 取出对象
  16. public function make($alias, $params = [])
  17. {
  18. return call_user_func_array($this->instanles[$alias], $params);
  19. }
  20. }
  21. // 控制器
  22. class Controller
  23. {
  24. // public function index(): string
  25. // {
  26. // return (new View())->fetch((new \test\Model())->select()['data']);
  27. // }
  28. /*依赖注入*/
  29. // protected $model;
  30. // protected $view;
  31. //
  32. // public function __construct($model, $view)
  33. // {
  34. // $this->model = $model;
  35. // $this->view = $view;
  36. // }
  37. //
  38. // public function index(): string
  39. // {
  40. // return $this->view->fetch($this->model->select()['data']);
  41. // }
  42. /*服务容器*/
  43. public function index(Container $instanles)
  44. {
  45. return $instanles->make('view')->fetch($instanles->make('model')->select()['data']);
  46. }
  47. }

index.php

  1. <?php
  2. /*服务容器*/
  3. require './Controller.php';
  4. $container = new \test\Container();
  5. $container->bind('model', function (){return new \test\Model();});
  6. $container->bind('view', function (){return new \test\View();});
  7. $table = new \test\Controller();
  8. ?>
  9. <!DOCTYPE html>
  10. <html lang="en">
  11. <head>
  12. <meta charset="utf-8">
  13. <title>mvc</title>
  14. </head>
  15. <body>
  16. <?php echo $table->index($container);?>
  17. </body>
  18. </html>

更多相关文章

  1. 多文件上传、MVC依赖注入与服务容器
  2. 多文件上传-MVC依赖注入-容器管理依赖对象实现
  3. 你在 Python 中常常写的 with..as.. 到底是个啥?
  4. JVM垃圾回收机制
  5. 在聊Java中的equals方法
  6. JSON、AJAX初学习+简上手
  7. 除了 Docker,我们还有哪些选择?
  8. 【asp.net core 系列】14 .net core 中的IOC
  9. C# 数据操作系列 - 11 NHibernate 配置和结构介绍

随机推荐

  1. Android单元测试(七):Robolectric,在JVM上调
  2. Android多分辨率适配框架(1)— 核心基础
  3. Android(安卓)Studio3.3打开Android(安卓
  4. android:radius设置圆角失败的问题
  5. Android进阶——Android视图工作机制之me
  6. Android 模拟器安装及使用教程
  7. Android软件的自动更新
  8. 欢迎进入Android的世界
  9. Android之我当年爬过的坑
  10. Android修改APP版本号