自己手写一个简易的MVC框架
mvc结构分为: m(model) - v(view) - c(controller).
其中m和v可用第三方包实现,而c这需要自己实现(原因: c是业务逻辑实现区,充满了不确定性).
m用到的第三方库为: catfan/medoo
v用到的第三方库为: league/plates
具体实现步骤步骤
- 创建一个项目目录
testFrame
在此目录下分别创建application
和core
目录 - 安装第三方包
- 安装catfan/medoo:
composer require catfan/medoo
- 安装league/plates:
composer require league/plates
- 最终目录结构
- 安装catfan/medoo:
- 在core目录中新建Model和View脚本并在其中导入第三方包
- Model.php的代码:
<?php
namespace core;
use Medoo\Medoo;
class Model extends Medoo
{
public function __construct(array $options)
{
parent::__construct($options);
}
}
- View.php的代码:
3.最终目录<?php
namespace core;
use League\Plates\Engine;
class View extends Engine
{
public function __construct($directory = null, $fileExtension = 'php') { parent::__construct($directory, $fileExtension); }
}
- Model.php的代码:
在
application
目录下创建三个目录,分别是models, views, controllers
- 在
models
目录下新建StaffsModel.php
,获取员工表的数据. - 在
views
目录下新建staffs目录
,创建显示员工数据的视图list.php
(html). - 在
controllers
目录下创建StaffsController.php
,把员工数据(StaffsModel
)插入到视图(StaffsView
)中.
具体代码:
StaffsController.php
```phpt<?php
namespace controllers;
use Closure;
// 服务容器
class Container
{
protected $instanles;
// 插入外部依赖
public function bind($alias, Closure $process)
{
$this->instanles[$alias] = $process;
}
// 取出外部依赖
public function make($alias, $params = []):object
{
return call_user_func_array($this->instanles[$alias], $params);
}
}
// 门面
class Facade
{
protected static $container = null;
// 构造函数,初始化$container
public static function initialize(Container $container)
{
static::$container = $container;
}
}
// 静态化模型类
class StaticStaffModel extends Facade
{
public static function select($tablename, $field, $condition)
{
return static::$container->make('model')->select($tablename, $field, $condition);
}
}
// 静态化视图类
class StaticStaffView extends Facade
{
public static function fetch($path, $data)
{
return static::$container->make('view')->render($path, ['staffs' => $data]);
}
}
// 控制器
class StaffController
{
public function __construct(Container $container)
{
Facade::initialize($container);
}
public function index($tablename, $field, $condition, $path)
{
$data = StaticStaffModel::select($tablename, $field, $condition);
return StaticStaffView::fetch($path, $data);
}
}
> StaffsModel.php
```phpt
<?php
namespace models;
use testFrame\core\Model;
class StaffModel extends Model
{
public function __construct(array $options)
{
parent::__construct($options);
}
}
staffs/list.php
```html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>员工信息</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
}
table {
border-collapse: collapse;
border: 1px solid;
width: 50%;
text-align: center;
}
th,
td {
border: 1px solid;
padding: 5px;
}
tr:first-child {
background-color: #eee;
}
</style>
</head>
<body>
<h3>用户管理系统</h3>
<table>
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
<th>工资</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<?php foreach ($staffs as $staff): ?>
<tr>
<td><?= $this->e($staff['sid']) ?></td>
<td><?= $this->e($staff['name']) ?></td>
<td><?= $this->e($staff['gender']) == 'male' ? '男' : '女' ?></td>
<td><?= $this->e($staff['salary']) ?></td>
<td><?= $this->e($staff['email']) ?></td>
<td>
<button>编辑</button>
<button>删除</button>
</td>
</tr>
<?php endforeach ?>
</table>
<p>
<a href="">1</a>
<a href="">2</a>
<a href="">3</a>
<a href="">4</a>
<a href="">5</a>
<a href="">6</a>
</p>
</body>
</html>
- 在
5. 在`composer.json`中添加*autoload*,然后在控制台执行`composer dump`.注意,控制台路径要在当前目录下.
```json5
{
"name": "zhang/null",
"description": "this is a test",
"require": {
"catfan/medoo": "^1.7",
"league/plates": "^3.4"
},
"autoload": {
"classmap": [
"application/controllers",
"application/models",
"application/views",
"core"
]
}
}
- 测试,在根目录下创建一个
index.php
进行测试,具体代码如下:
<?php
use testFrame\core\View;
use models\StaffModel;
use controllers\Container;
use controllers\StaffController;
require_once './vendor/autoload.php';
$container = new Container();
$container->bind('view', function () { return new View('application/views'); });
$container->bind(
'model', function () {
$config = [
'database_type' => 'mysql',
'database_name' => 'phpedu',
'server' => 'localhost',
'username' => 'admin',
'password' => '123456',
];
return new StaffModel($config);
}
);
$controller = new StaffController($container);
echo $controller->index('staffs', ['sid', 'name', 'age', 'gender', 'salary', 'birthday'], ['LIMIT' => [20, 10]], 'staffs/list');
效果:
)