博客列表 >PHP基础:利用composer手写一个MVC小框架

PHP基础:利用composer手写一个MVC小框架

暴宇
暴宇原创
2020年06月04日 20:37:271095浏览

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);

    2.5执行效果图


    3.总结

    3.1 composer的文件自动加载器非常好用,只需加载一个文件即可

    3.2 composer的第三方组件非常多,需要什么组件就到网站https://packagist.org/ 上搜

    3.3 MVC框架的好处就是利用控制器调用模型类查询数据,再利用视图类渲染输出,就一个入口,便可通过控制器操作多个页面

    声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
    全部评论
    文明上网理性发言,请遵守新闻评论服务协议