## 创建core/database/model/Model.php
```
<?php
namespace core\database\model;
class Model
{
// 绑定的数据库连接
protected $connection;
protected $table; // 表
protected $paimaryKey; // 主键
protected $timestamps = true; // 是否自动维护时间字段
/*
为什么要分开两个属性?
$orginal 原的数据
$attriubte 原数据的复制版 用户只能修改这个 !
然后跟$original相比较 得出用户修改的数据字段
*/
protected $original;
protected $attribute;
public function __construct()
{
// 给当前模型绑定一个数据库连接
$this->connection = \App::getContainer()->get('db')->connection(
$this->connection
);
}
// 获取表名称 没有表名称 就返回 模型(小写)+s
public function getTable()
{
if( $this->table)
return $this->table;
$class_name = get_class($this);
$class_arr = explode('\\',$class_name);
$table = lcfirst(end(
$class_arr
));
return $table .'s';
}
public function setOriginalValue($key, $val)
{
if(! $this->original)
$this->original = new \stdClass();
$this->original->$key = $val;
}
public function setAttribute($key, $val)
{
if(! $this->attribute)
$this->attribute = new \stdClass();
$this->attribute->$key = $val;
}
// 见最上面的说明
public function __set($key, $value)
{
$this->setAttribute($key, $value);
}
// 属性 同步 original
public function syncOriginal()
{
$this->attribute = $this->original;
}
/**
* 返回用户改过的数据
* @return array
* @example ['id' => 3,'user_id' => '3']
*/
public function diff()
{
$diff = [];
if( $this->attribute == $this->original) // 没改变
return $diff;
foreach ($this->original as $origin_key => $origin_val)
if( $this->attribute->$origin_key != $origin_val) // 改变了
$diff[$origin_key] = $this->attribute->$origin_key;
return $diff;
}
public function __get($name)
{
return $this->attribute->$name;
}
// 托管到 __call
//因此: User::where() 与 (new User)->where() 是一样的
public static function __callStatic($method, $args)
{
return (new static())->$method(...$args);
}
public function __call($method, $args)
{
return (new Builder(
$this->connection->newBuilder()
))
->setModel($this)
->$method(...$args);
}
}
````
## 创建core/database/model/Builder.php
```
<?php
namespace core\database\model;
class Builder
{
protected $query;
protected $model;
public function __construct($query)
{
$this->query = $query;
}
public function setModel(Model $model)
{
$this->model = $model;
return $this;
}
public function __call($method, $args)
{
$this->query->$method(...$args);
return $this;
}
public function get($columns = ['*'])
{
if(! is_array($columns))
$columns = func_get_args();
$this->query->columns = $columns;
$this->query->table( $this->model->getTable());
$sql = $this->query->toSql();
return $this->bindModel(
$this->query->runSql($sql)
);
}
// 数据映射模式 把数据映射到模型
//模型的本质: 每条数据都是一个模型(对象)
protected function bindModel($datas)
{
if(! is_array($datas))
$datas[] = $datas;
$models = [];
foreach ($datas as $data){ // 多少条数据就多少个模型
$model = clone $this->model; // 原型模式
foreach ($data as $key => $val)
$model->setOriginalValue($key, $val);
$model->syncOriginal(); // 把attriubtes = orginal
$models[] = $model;
}
return $models;
}
}
```
## 编辑app/User.php 继承模型基础类
![](https://img.kancloud.cn/a4/69/a469507e60982a6a0754d7e25682e78a_1311x630.png)
## 运行
由于每条数据都是一个类,所以可以调用方法。
![](https://img.kancloud.cn/8c/ed/8cedf0e02c378211d95918bf102adc13_553x156.png)
![](https://img.kancloud.cn/29/b3/29b33c1d7d2d2eec98d116a89372dd80_595x268.png)
- 前言
- 基础篇
- 1. 第一步 创建框架目录结构
- 2. 引入composer自动加载
- 3. php自动加载 (解释篇)
- 4. 创建容器 注册树模式
- 5. 关于psr规范解释
- 6. 关于"容器" "契约" "依赖注入" (解释篇)
- 7. 添加函数文件helpers.php
- 8. 初始化请求(Request)
- 9. 响应 (Response)
- 10. 路由一 (路由组实现)
- 11. 路由二 (加入中间件)
- 12. 配置信息 (类似laravel)
- 13. 数据库连接 (多例模式)
- 14. 查询构造器 (query builder)
- MVC实现
- M 模型实现 (数据映射 + 原型 模式)
- C 控制器实现 + 控制器中间件
- V 视图实现 (Laravel Blade 引擎)
- V 视图切换成 ThinkPhp 模板 引擎)
- 其他轮子
- 日志
- 自定义异常 (异常托管)
- 单元测试 (phpunit)
- 替换成swoole的http服务器
- 协程上下文解决request问题
- qps测试
- 发布到packagist.org