PHP基础:利用composer手写一个MVC小框架
1.在你的系统上安装composer并在项目中使用它;
(1)到composer中文网上下载composer安装文件https://www.phpcomposer.com/
(2)安装composer到你的系统上,安装后即可在任意目录运行composer命令
(3)创建项目目录并在项目中安装composer的项目依赖
2.在项目目录中创建MVC文件
2.1在项目目录里建立以下文件夹及相关文件:
app(用于存放MVC文件)
view.php
model.php
controller.php
controllers(放控制器类文件);
models(放模型类文件);
views(放视图文件);
core(用于存放核心公共类库)
automodel.php(用于继承第三方模型类库,作为本项目的公共模型类库)
autoview.php(用于继承第三方视图类库,作为本项目的公共视图类库)
小框架文件目录结构图如下:
2.2加载第三方类库
模型类库采用catfan/medoo
视图类库采用league/plates
2.3编写core核心类库
core/automodel.php公共模型类代码
// 核心库命名空间需与目录core同名namespace core;// 引入第三方模型类库use Medoo\Medoo;// 公共模型继承自第三方模型类库class automodel extends Medoo{ // 构造方法 public function __construct() { // 数据库连接信息 $options=[ 'database_type' => 'mysql', 'database_name' => 'study', 'server' => 'localhost', 'username' => 'root', 'password' => 'root', 'charset' => 'utf8' ]; // 继承第三方模型类库的构造方法,并将数据库连接信息传给它 parent::__construct($options); }}
core/autoview.php公共视图类代码
// 核心库命名空间需与目录core同名namespace core;// 引入第三方模型类库use League\Plates\Engine;// 公共视图继承自第三方视图类库class autoview extends Engine{ // 新建一个属性,用于存放第三方类库返回的对象 private $templates; // 构造方法,将视图文件地址传给第三方类库 public function __construct($path) { $this->templates=parent::__construct($path); }}
2.4编写MVC小框架
app/models/model.php模型类代码
// 模型类文件// 命名空间需与目录名一致namespace models;use core\automodel as CoreModel;// 模型类继承自公共模型库,公共模型库又继承自第三方模型库class model extends CoreModel{ // 测试代码 // public function getdata(){ // return 'getdata'; // } // 这里一行代码都没写,一样可以调用第三方模型库的方法}
app/views/view.php视图页面代码
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { margin: 0; padding: 0; box-sizing: border-box; color: #555;}body { display: flex; flex-direction: column; align-items: center;}/*表格样式*/table { width: 80%; border: 1px solid; border-collapse: collapse; text-align: center;}table caption { font-size: 1.2rem; margin: 10px;}table td,table th { border: 1px solid; padding: 5px;}table tr:hover { background-color: #eee;}table thead tr:only-of-type { background-color: lightblue;}table button { width: 56px; height: 26px;}table button:last-of-type { color: red;}table button { cursor: pointer; margin: 0 3px;}/*分页条样式*/body > p { display: flex;}p > a { text-decoration: none; color: #555; border: 1px solid; padding: 5px 10px; margin: 10px 2px;}p > input:first-of-type { /* text-decoration: none; */ color: #555; /* border: 1px solid; */ padding: 5px 10px; margin: 10px 2px; height: 40px; width: 50px;}.active { background-color: red; color: white; border: 1px solid red;} </style> <title>材料管理系统</title></head><body> <h3>材料管理系统</h3> <table> <tr> <th>ID</th> <th>名称</th> <th>规格</th> <th>描述</th> <th>数量</th> <th>单位</th> </tr> <?php foreach($datas as $data):?> <tr> <td><?=$this->e($data['id']) ?></td> <td><?=$this->e($data['name']) ?></td> <td><?=$this->e($data['DN']) ?></td> <td><?=$this->e($data['describe']) ?></td> <td><?=$this->e($data['number']) ?></td> <td><?=$this->e($data['unit']) ?></td> </tr> <?php endforeach;?> </table> <?php// 1. 分页条显示5个页码$showPages = $limit;// 2. 分页条的起始页码$startPage = 1;// 3. 分页条的终止页码$endPage = $pages; // 当前总页数: 14// 4. 分页条的偏移量: (当前分页条显示的页码数 - 1) / 2$offsetPage = ($showPages -1) / 2; // 2// 只有当前分页条数量 < 总页数, 才有必要显示出省略标记if ($showPages < $pages) { // 如果当前页 > 偏移量 + 1 , 应该显示... if ($page > $offsetPage + 1) { $startOmit = '...'; } // 将当前分页条页码重置 if ($page > $offsetPage) { $startPage = $page - $offsetPage; $endPage = $page + $offsetPage; if ($endPage > $pages) {$endPage = $pages;} } else { $startPage = 1; $endPage = $showPages; } // 如果当前页 + 偏移量 > 总页数 if ($page + $offsetPage > $pages) { // 原理, 就是向当前页前面进行借位 // 此时, 新的起点 = 当前位置 - (当前页 + 偏移量 - 原始位置) $startPage = $startPage - ($page + $offsetPage - $endPage); } if ($showPages < $pages && $page + $offsetPage < $pages) $endOmit = '...';}?><p><!-- 首页 --><a href="<?php echo $_SERVER['PHP_SELF'] . '?p=1' ?>">首页</a><!-- 前一页 --><?php$prev = $page - 1;if ($page == 1) $prev = 1; ?><a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $prev ?>">前一页</a><?php if (isset($startOmit)) : ?> <a href="#"><?php echo $startOmit ?></a> <?php endif ?> <?php for ($i=$startPage; $i<=$endPage; $i++): ?> <?php $jump = sprintf('%s?p=%s', $_SERVER['PHP_SELF'], $i ); $active = ($i == $page) ? 'active' :null; ?> <a href="<?php echo $jump ?>" class="<?php echo $active ?>"><?php echo $i ?></a> <?php endfor ?> <?php if (isset($endOmit)) : ?> <a href="#"><?php echo $endOmit ?></a> <?php endif ?><!-- 下一页 --><?php$next = $page + 1;if ($page == $pages) $next = $pages; ?><a href="<?php echo $_SERVER['PHP_SELF'] . '?p=' . $next ?>">下一页</a><!-- 尾页 --><a href="<?php echo $_SERVER['PHP_SELF'] . '?p='. $pages ?>">尾页</a></p><p> <!-- 直接跳转 --><form id="topage" action="<?php echo $_SERVER['PHP_SELF'] ?>" method="get"> <label for="p">跳转到:</label> <input id='p' type="text" name='p'> <input type="submit" value="跳转" form="topage"></form></p></body></html>
app/controllers/controller.php控制器代码
// 控制器文件// 命名空间需与目录名一致namespace controllers;// 类名需与文件名一致class controller{ // 共享模型 private $model; // 共享视图 private $view; // 构造方法 public function __construct($model,$view) { // 将初始化控制时拿到的模型类和视图类共享 $this->model=$model; $this->view=$view; } // 查询总记录数 public function count(){ // 使用第三方类库的count方法获取总记录数 return $this->model->count('goods'); } public function select($offset,$limit,$page,$pages){ // 执行medoo里面的select方法,传参['表名','字段列表','条件列表'] $selectdata=$this->model->select('goods',['id','name','DN','describe','number','unit'],['LIMIT'=>[$offset,$limit]]); // 打印查询到的数据 // var_dump($selectdata); // 将数据通过第三方view类库和view页面进行渲染后返回 return $this->view->render('view',['datas'=>$selectdata,'page'=>$page,'pages'=>$pages,'limit'=>$limit]); }}
index.php(项目根目录下的首页文件)
// 主页// 引入composer的文件自动加载器require 'vendor/autoload.php';// 引入所需类方法,别名就是类名称use controllers\controller;use models\model;use core\autoview;// 调用类方法测试自动加载// 控制器// echo (new controller)->index();// // 模型// echo (new model)->getdata();// // 视图// echo (new controller)->showview();// 引入正式模型类$model=new model;// var_dump($model);// echo '<hr>';// 引入正式视图类$view=new autoview('app/views');// var_dump($view);// echo '<hr>';// 初始化控制器,并将模型类和视图类传给控制器$controller=new controller($model,$view);// var_dump($controller);// 1. 获取当前的页码,如果GET不到p值,默认为1$page = $_GET['p'] ?? 1;// 2. 每页显示的记录数量$limit = 5;// 3. 总页数// 计算总页数:获取到所有数据行数/每页显示的数量,并向上取整$pages= ceil($controller->count()/$limit);// 4. 偏移量$offset = $limit * ($page - 1);// 将分页参数及偏移量传给控制器,再由控制器输出view视图echo $controller->select($offset,$limit,$page,$pages);