用php手写一个简单的MVC框架只需要几十行代码

bloger 2020-07-29 PM 550℃ 1条

说到php框架就不得不提MVC,现在主流框架都沿用的MVC的架构思想;

我们学php初都会学习MVC,学习其运行流程、学其面向对象的思想;

先来回顾一下MVC:

MVC概念

MVC包括控制器(Controller),模型(Model),视图(View)。

控制器的作用是调用模型和 视图,将模型产生的数据传递给视图,并让视图去显示

模型的作用是获取数据并处理返回数据

视图的作用是将取得的数据进行美化,并向用户终端输出

(2)执行过程

  1. 浏览者 -> 调用控制器,发出指令
  2. 控制器 -> 按指令选择合适的模型
  3. 模型 -> 按指令取数据
  4. 控制器 -> 按指令选视图
  5. 视图 -> 把取到的数据展示出来

composer之前MVC框架的加载方式都是使用的文件引入的方式(include);

再使用 spl_autoload_register()进行注册;

现在composer流行,我们写一个mvc框架就变得更加的简单,文件全部是用composer加载;

现在我们来编写一个简单的MVC框架;

首先定义下规则,看个人喜好:

  1. 所有文件都以小写命名;
  2. 命名空间以小写开头;
  3. 视图以小写开头;
  4. 控制器统一不带controller;

支持单模块独立绑定域名;

1、首先安装composer建议全局安装;具体参考composer官网

2、创建框架目录如下
2B594987-E075-4d63-A71C-7AA0D78032FB.png

app --- 应用目录(区分模块)
conf --- 配置目录(dev、pro、test)区分环境
libs --- 核心类库文件
public --- 公共目录(区分模块)
static --- 静态资源

3、项目新建立composer.json文件,内容如下:

{
  "authors": [
    {
      "name": "yiijun",
      "email": "251784425@qq.com"
    }
  ],
  "require": {
    "php": ">=7.0.4"
  },
  "autoload": {
    "psr-4": {"libs\\": "libs/","app\\":"app/"}
  }
}

重点是autoload:目前我们这个框架需要自动加载的目录为,libs与app

4、cd 到项目目录下执行composer update
DD2C831F-FE1A-4fca-BCCB-17ED26649E68.png

5、暂定项目名称为simple-php,编写解析路由核心类文件,libs/framework/simple.php,一个mvc的核心也就是这里了;


<?php
// +----------------------------------------------------------------------
// | Created by [ PhpStorm ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016.
// +----------------------------------------------------------------------
// | Create Time (2020-07-28 16:05)
// +----------------------------------------------------------------------
// | Author: 唐轶俊 <tangyijun@021.com>
// +----------------------------------------------------------------------
namespace libs\framework;
class Simple
{
    protected $config = [];

    public function __construct($config = [])
    {
        $this->config = $config;
    }

    public function run()
    {
        //路由解析
        $this->route();

        //设置错误级别
        $this->setReporting();
    }

    public function route()
    {
        $controllerName = $this->config['controller'];
        $actionName = $this->config['action'];
        $params = [];
        $url = $_SERVER['REQUEST_URI'];
        $position = strpos($url, '?');
        $url = $position === false ? $url : substr($url, 0, $position);
        $url = trim($url, '/');
        if ($url) {
            $urlArray = explode('/', $url);
            $urlArray = array_filter($urlArray);

            //获取控制器名称
            $controllerName = ucfirst($urlArray[0]);
            array_shift($urlArray);

            //获取方法名称
            $actionName = $urlArray ? $urlArray[0] : $actionName;
            array_shift($urlArray);

            //获取参数
            $params = $urlArray ? $urlArray : array();
        }

        //获取模块名称
        $module = substr(APP_PATH,strrpos(str_replace('\\','/',APP_PATH),"/") + 1);
        $controller = 'app\\'.$module.'\\controller\\'. $controllerName;

        //过滤
        if ($controller && !preg_match('/^[A-Za-z](\w|\.)*$/', $controller) && !class_exists($controller)) {
            exit($controller . '控制器不存在');
        }
        if (!method_exists($controller, $actionName)) {
            exit($actionName . '方法不存在');
        }
        $dispatch = new $controller($controllerName, $actionName);
        call_user_func_array(array($dispatch, $actionName), $params);
    }



    public function setReporting()
    {
        if (APP_DEBUG === true) {
            error_reporting(E_ALL);
            ini_set('display_errors','On');
        } else {
            error_reporting(E_ALL);
            ini_set('display_errors','Off');
            ini_set('log_errors', 'On');
        }
    }
}

6、首先我们在app目录下建立文件夹admin模块作为后台;

7、建立文件init.php,定义常量和环境变量,加载composer

<?php
// +----------------------------------------------------------------------
// | Created by [ PhpStorm ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016.
// +----------------------------------------------------------------------
// | Create Time (2020-07-28 16:05)
// +----------------------------------------------------------------------
// | Author: 唐轶俊 <tangyijun@021.com>
// +----------------------------------------------------------------------
$host_name = gethostname();
if(in_array($host_name, ['VM_48_39_centos'])) {
    define('LIB_ENV', 'pro');
} else if(in_array($host_name, ['10-9-115-74'])) {
    define('LIB_ENV', 'test');
} else {
    define('LIB_ENV', 'dev');
}

define('APP_PATH', dirname(__FILE__));
define('APP_DEBUG', true);
require __DIR__ . '/../../vendor/autoload.php';

//加载配置
$config = require_once __DIR__ . '/../../conf/'.LIB_ENV.'/conf_admin.php';
$app = new \libs\framework\Simple($config);

8、建立项目入口文件:publicadminindex.php,运行项目

require __DIR__ . '/../../app/admin/init.php';
$app->run();

9、建立基础控制器、controller.php 放在:/libs/franework/base/controller.php


<?php
// +----------------------------------------------------------------------
// | Created by [ PhpStorm ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016.
// +----------------------------------------------------------------------
// | Create Time (2020-07-29 10:06)
// +----------------------------------------------------------------------
// | Author: 唐轶俊 <tangyijun@021.com>
// +----------------------------------------------------------------------
namespace libs\framework\base;
class Controller
{
    protected $controller;

    protected $action;

    protected $view;

    public function __construct($controller,$action)
    {
        $this->controller = $controller;
        $this->action = $action;
        $this->view = new View($this->controller,$this->action);
    }


    public function assign($name, $value)
    {
        $this->view->assign($name, $value);
    }


    public function render()
    {
        $this->view->render();
    }
}

10、建立基础视图、controller.php 放在:/libs/framework/base/view.php


<?php
// +----------------------------------------------------------------------
// | Created by [ PhpStorm ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016.
// +----------------------------------------------------------------------
// | Create Time (2020-07-29 9:57)
// +----------------------------------------------------------------------
// | Author: 唐轶俊 <tangyijun@021.com>
// +----------------------------------------------------------------------
namespace libs\framework\base;
class View
{
    protected $controller;

    protected $action;

    protected $variables = [];

    public function __construct($controller,$action)
    {
        $this->controller = $controller;
        $this->action = $action;
    }

    /**
     * @param $name
     * @param $value
     * 渲染变量
     */
    public function assign($name,$value)
    {
        $this->variables[$name] = $value;
    }

    /**
     * 加载视图
     */
    public function render()
    {
        //变量赋值
        extract($this->variables);

        //获取视图路径
        $layout = APP_PATH . '/view/' . strtolower($this->controller) . '/' . ucwords($this->action) . '.html';

        if (is_file($layout)) {
            include $layout;
        } else {
            echo "<h1>无法找到视图文件</h1>";
        }
    }
}

11、在admin模块中建立首页控制器,/app/admin/controller/index.php

<?php
// +----------------------------------------------------------------------
// | Created by [ PhpStorm ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016.
// +----------------------------------------------------------------------
// | Create Time (2020-07-28 17:14)
// +----------------------------------------------------------------------
// | Author: 唐轶俊 <tangyijun@021.com>
// +----------------------------------------------------------------------
namespace app\admin\controller;
use libs\framework\base\Controller;

class Index extends Controller
{
    public function index()
    {
        $this->assign('hello','hello world');
        $this->render();
    }
}

12、在admin模块中建立首页视图,/app/admin/view/index.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<?php echo $hello?>

</body>
</html>

13、绑定域名:


<VirtualHost *:80>
    DocumentRoot "D:\phpStudy\WWW\simple-php\public\admin"
    ServerName admin.simple-php.com
    ServerAlias 
  <Directory "D:\phpStudy\WWW\simple-php\public\admin">
      Options FollowSymLinks ExecCGI
      AllowOverride All
      Order allow,deny
      Allow from all
      Require all granted
      RewriteEngine On
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteRule .* index.php #重定向
  </Directory>
</VirtualHost>

14、访问域名

{7CA26FC6-CC3F-4534-A2EE-C72D4E426CEC}_20200729145952.jpg

该框架的核心就是实用composer加载类文件、而不用实用引入的方式;使代码更加简洁、用起来更加的方便;

该框架我封装了一些常用的核心类文件;

比如:

  1. redis
  2. curl
  3. upload
  4. redis
  5. session
  6. log
  7. db
  8. apcu
  9. 通用函数

等类文件,可以直接使用;

项目放在githup上地址为:

https://github.com/yiijun/simple-php

标签: 框架, mvc

非特殊说明,本博所有文章均为博主原创。

评论啦~



唉呀 ~ 仅有一条评论


  1. 站元素主机
    站元素主机

    学习了,赞一个

    回复 2020-11-03 15:26