## 创建core/database/model/Model.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
```
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)