欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于composer的MVC小框架实例

程序员文章站 2022-03-24 21:17:16
...

composer框架介绍

1. 架构

  • M: Model, 模型, 使用第三方组件来实现它
  • V: View, 视图, 使用第三方组件来实现它
  • C: Controller, 控制器, 我们的业务逻辑全部写到控制器中

2. 第三方包

  • Model: composer require catfan/medoo
  • View: composer require league/plates

3. 目录

  • app 目录: 用户应用,按 mvc 框架创建
  • core 目录: 框架的核心代码,创建自己的模型类与视图类
  • vendor 目录:composer与第三方组件存储目录

4.流程

  • 在项目目录下使用composer命令进行组件的安装
  • 在核心core目录创建MVC文件,去继承第三方组件,然后编写公用的方法或属性给用户应用的MVC文件使用
  • APP目录是用户应用的MVC文件,分别创建文件夹进行存放,里面的MVC文件继承核心的MVC文件,进行实际的用户应用代码编写/组件的实际调用
  • 创建好文件和命名空间后在composer.json文件中autoload进行PSR-4加载
  • 编写入口文件,引入composer的自动加载,进行路由访问
  • 我的方式是将model文件直接引入到controller文件中使用,需要使用到什么model就引入什么model,核心的view直接给核心的controller引入实例化赋值到属性$view中存储起来使用,用户应用控制器都需要视图调用,而且视图类文件只有一个,只需传入参数即可

目录图片:
基于composer的MVC小框架实例


组件的具体使用查看组件的介绍文档,以下部分是core目录的代码:

Controller.php

  1. <?php
  2. namespace core;
  3. use core\View;
  4. // 自定义核心控制器
  5. abstract class Controller
  6. {
  7. // 每一个控制器都需要调用到视图组件,实例化存储到属性view中
  8. protected $view = '';
  9. // 构造函数,进行视图类的实例赋值到属性view
  10. public function __construct()
  11. {
  12. $this->view = new View('app/views');
  13. }
  14. }

Model.php

  1. <?php
  2. // 模型类
  3. namespace core;
  4. // 模型类继承自 组件Medoo
  5. use Medoo\Medoo;
  6. abstract class Model extends Medoo
  7. {
  8. public function __construct()
  9. {
  10. $optinos = [
  11. 'database_type' => 'mysql',
  12. 'database_name' => 'phpedu',
  13. 'server' => 'localhost',
  14. 'username' => 'root',
  15. 'password' => 'root',
  16. ];
  17. parent::__construct($optinos);
  18. }
  19. }

View.php

  1. <?php
  2. // 视图类
  3. namespace core;
  4. // 视图类继承自 plates组件
  5. use League\Plates\Engine;
  6. class View extends Engine
  7. { public $templates = null;
  8. public function __construct($path)
  9. {
  10. $this->templates = parent::__construct($path);
  11. }
  12. }

以下是app目录用户应用:
controllers/UsersController.php

  1. <?php
  2. namespace controllers;
  3. use core\Controller;
  4. use models\UsersModel;
  5. // 继承核心controller
  6. class UsersController extends Controller
  7. {
  8. public function __construct()
  9. {
  10. // 可以不写,但最好调用一下父类的构造方法
  11. parent::__construct();
  12. }
  13. // 首页展示方法
  14. public function index()
  15. {
  16. $model = new UsersModel();
  17. $users = $model ->select('users',['id','name','email'],['id[>]'=>20,'LIMIT'=>5]);
  18. return $this->view->render('users/list',['users'=>$users]);
  19. }
  20. // 删除数据方法
  21. public function delete()
  22. {
  23. $id = $_GET['id'];
  24. $model = new UsersModel();
  25. $result = $model->delete("users", [
  26. "id" => $id
  27. ]);
  28. // return __METHOD__;
  29. return $result->rowCount();;
  30. }
  31. // 展示修改页面
  32. public function edit()
  33. {
  34. $id = $_GET['id'];
  35. $model = new UsersModel();
  36. $user = $model->get("users", ['id','name','email'], [
  37. "id" => $id
  38. ]);
  39. return $this->view->render('users/edit',['user'=>$user]);
  40. // return print_r($_GET,true);
  41. }
  42. // 更新数据方法
  43. public function update()
  44. {
  45. $id = $_GET['id'];
  46. $model = new UsersModel();
  47. $data = $model->update("users", [
  48. "name" => $_POST['name'],
  49. "email" =>$_POST['email']
  50. ], [
  51. "id" => $id
  52. ]);
  53. return $data->rowCount();
  54. // return print_r($_POST,true);
  55. }
  56. }

models/UsersModel.php

  1. <?php
  2. namespace models;
  3. use core\Model;
  4. // 继承核心的Model
  5. class UsersModel extends Model
  6. {
  7. public function __construct()
  8. {
  9. parent::__construct();
  10. }
  11. // 自行创建model组件中没有的方法/定制式的方法
  12. public function idGetDate()
  13. {
  14. return '自定义模型数据处理';
  15. }
  16. }

Views文件夹主要存放的是视图文件,查看组件文档有几点重点:

  • 视图/模板文件通常会与控制器中的一个方法对应
  • 根据控制器不同,创建不同的目录来存放这些视图/模板文件
  • 视图下面的目录与控制器对应
  • 视图下面的控制器对应的目录下面是与控制器方法对应的模板文件

users/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. body {
  9. display: flex;
  10. flex-direction: column;
  11. align-items: center;
  12. }
  13. table {
  14. border-collapse: collapse;
  15. border: 1px solid;
  16. width: 50%;
  17. text-align: center;
  18. }
  19. th,
  20. td {
  21. border: 1px solid;
  22. padding: 5px;
  23. }
  24. tr:first-child {
  25. background-color: #eee;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <h3>用户管理系统</h3>
  31. <table>
  32. <tr>
  33. <th>id</th>
  34. <th>姓名</th>
  35. <th>邮箱</th>
  36. <th>操作</th>
  37. </tr>
  38. <?php foreach ($users as $user): ?>
  39. <tr>
  40. <!-- $this->e:模板引擎Plates中的一个函数,用来过滤特殊字符 -->
  41. <td><?=$user['id']?></td>
  42. <td><?=$this->e($user['name'])?></td>
  43. <td><?=$this->e($user['email'])?></td>
  44. <td><button onclick="location.href='/mvc/index.php/users/edit.html?id=<?=$user['id']?>'" >编辑</button>
  45. <button onclick="del(<?=$user['id']?>)">删除</button></td>
  46. </tr>
  47. <?php endforeach ?>
  48. </table>
  49. <p>
  50. <a href="">假分页</a>
  51. <a href="">1</a>
  52. <a href="">2</a>
  53. <a href="">3</a>
  54. <a href="">4</a>
  55. </p>
  56. </body>
  57. <script>
  58. function del(id){
  59. let url = '/mvc/index.php/users/delete.html?id='+id;
  60. return confirm('是否删除?') ?location.href=url : false;
  61. }
  62. </script>
  63. </html>

users/edit.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="/mvc/index.php/users/update.html?id=<?=$this->e($user['id'])?>" method="POST" >
  10. <fieldset>
  11. <legend>用户编辑</legend>
  12. <p>
  13. <label for="">用户名:</label>
  14. <input type="text" name="name" id="name" value="<?=$this->e($user['name'])?>" >
  15. </p>
  16. <p>
  17. <label for="">邮箱:</label>
  18. <input type="email" name="email" id="email" value="<?=$this->e($user['email'])?>">
  19. </p>
  20. <p>
  21. <button>保存</button>
  22. </p>
  23. </fieldset>
  24. </form>
  25. </body>
  26. </html>

创建入口文件index.php

  1. <?php
  2. //加载composer的自动加载文件
  3. require __DIR__ . '/vendor/autoload.php';
  4. // 路由访问拦截
  5. $pathinfo = array_values(array_filter(explode('/', str_replace('.html','',$_SERVER['PATH_INFO']))));
  6. // 如果要用路由拦截访问,不能使用USE进行文件别名,
  7. $controller = '\\controllers\\' . ucfirst(array_shift($pathinfo)) . 'Controller';
  8. $action = array_shift($pathinfo);
  9. // 测试
  10. // echo $controller.'-'.$action;
  11. // printf('<pre>%s</pre>', print_r($pathinfo, true));
  12. $params = [];
  13. // 每次处理的是二个元素,所以$i = $i + 2
  14. for ($i=0; $i < count($pathinfo); $i+=2) {
  15. // $pathinfo中前一个元素是新数组中的键名, 后面一个是它的值
  16. if (isset($pathinfo[$i + 1])) {
  17. $params[$pathinfo[$i]] = $pathinfo[$i + 1];
  18. }
  19. }
  20. echo call_user_func_array([(new $controller), $action], $params );

访问地址是http://php.edu/mvc/index.php/users/index.html,直接访问index.php是会报错的因为没有控制器和方法,应该再优化一下,例如默认users控制器的index方法