## 模型定义
快速生成模型:
~~~
$php think make:model index@BlogModel
$php think make:model index@UserModel
~~~
模型实例:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
//自定义模型名
protected $name = 'user';
//自定义主键,可以是数组
protected $pk = 'uuid';
// 自定义表名称
protected $table = 'think_user';
// 自定义数据库连接
protected $connection = 'db_config';
// 开启自动写入时间戳字段,支持timestamp/datetime/int/false/true
protected $autoWriteTimestamp = 'datetime';
// 以下两行如果不写,默认为:create_time/update_time
protected $createTime = 'create_at';
protected $updateTime = 'update_at';
}
~~~
## 模型的属性
| 属性 | 描述 |
| --- | --- |
| name | 模型名(相当于不带数据表前后缀的表名,默认为当前模型类名) |
| table | 数据表名(默认自动获取) |
| suffix | 数据表后缀(默认为空) |
| pk | 主键名(默认为`id`) |
| connection | 数据库连接(默认读取数据库配置) |
| query | 模型使用的查询类名称 |
| field | 模型允许写入的字段列表(数组) |
| schema | 模型对应数据表字段及类型 |
| type | 模型需要自动转换的字段及类型 |
| strict | 是否严格区分字段大小写(默认为true) |
| disuse | 数据表废弃字段(数组) |
## 模型初始化
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
// `init`必须是静态方法,只在第一次实例化的时候执行一次
protected static function init()
{
//TODO:初始化内容
}
}
~~~
> 模型支持包括获取器、修改器、自动时间写入在内的一系列自动化操作和事件,简化了数据的存取操作。
## 模型操作
> 模型是数据库的增强版。
数据库操作:
~~~
Db::name('user')->where('id','>',10)->select();
~~~
改成模型操作:
~~~
/* 忽略了表名等模型中已包含的信息 */
User::where('id','>',10)->select();
~~~
第一种方式的查询结果是一个二维数组,而第二种方式的查询结果是包含了模型(集合)的数据集。不过,在大多数情况下,这两种返回类型的使用方式并无明显区别。
## 获取数据
在模型外部:
~~~
$user = User::find(1);
echo $user->create_time;
echo $user->name;
//使用了 `ArrayAccess` 接口
echo $user['create_time'];
echo $user['name'];
~~~
在模型内部:
~~~
$user = $this->find(1);
echo $user->getAttr('create_time');
echo $user->getAttr('name');
~~~
## 模型赋值
~~~
$user = new User();
$user->name = 'thinkphp';
$user->score = 100;
~~~
该方式赋值会自动执行模型的修改器,如果不希望执行修改器操作,可以使用:
~~~
$data['name'] = 'thinkphp';
$data['score'] = 100;
$user = new User($data);
~~~
`data`方法支持使用修改器
~~~
$user = new User();
$data['name'] = 'thinkphp';
$data['score'] = 100;
$user->data($data, true);
~~~
## 添加一条数据
第一种是实例化模型对象后赋值并保存:
~~~
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->save();
~~~
> `save`方法成功会返回`true`,一旦有错误就会抛出异常,无需判断返回值。
也可以直接传入数据到`save`方法批量赋值:
~~~
$user = new User;
$user->save([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
]);
~~~
默认只会写入数据表已有的字段。如果希望指定某些字段写入,可以使用:
~~~
$user = new User;
// post数组中只有name和email字段会写入
$user->allowField(['name','email'])->save($_POST);
~~~
最佳的建议是模型数据赋值之前就进行数据过滤,例如:
~~~
$user = new User;
// 过滤post数组中的非数据表字段数据
$data = Request::only(['name','email']);
$user->save($data);
~~~
`save`方法新增数据返回的是写入的记录数(通常是`1`)。
> 不要在同一个实例里面多次新增数据,如果确实需要多次新增,可以使用后面的静态方法处理。
## `Replace`写入
~~~
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->replace()->save();
~~~
## 获取自增ID
如果要获取新增数据的自增ID,可以使用下面的方式:
~~~
$user = new User;
$user->name = 'thinkphp';
$user->email = 'thinkphp@qq.com';
$user->save();
echo $user->id; // 获取自增ID,或者相应的主键pk
~~~
## 批量增加数据
支持批量新增,可以使用:
~~~
$user = new User;
$list = [
['name'=>'thinkphp','email'=>'thinkphp@qq.com'],
['name'=>'onethink','email'=>'onethink@qq.com']
];
$user->saveAll($list);
~~~
> saveAll方法新增数据返回的是包含新增模型(带自增ID)的数据集对象。
`saveAll`方法能自动识别数据是需要新增还是更新操作,当数据中存在主键的时候会认为是更新操作。
## 静态方法
还可以直接静态调用`create`方法创建并写入:
~~~
$user = User::create([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
]);
echo $user->name;
echo $user->email;
echo $user->id; // 获取自增ID
~~~
> 和`save`方法不同的是,`create`方法返回的是当前模型的对象实例。
`create`方法默认会过滤不是数据表的字段信息,可以在第二个参数传入允许写入的字段列表,例如:
~~~
// 只允许写入name和email字段的数据
$user = User::create([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
], ['name', 'email']);
echo $user->name;
echo $user->email;
echo $user->id; // 获取自增ID
~~~
支持`replace`操作,使用下面的方法:
~~~
$user = User::create([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com'
], ['name','email'], true);
~~~
## 建议的新增方式
新增数据的最佳实践原则:使用`create`方法新增数据,使用`saveAll`批量新增数据。
## 查找并更新
在取出数据后,更改字段内容后使用`save`方法更新数据。**这种方式是最佳的更新方式**。
~~~
$user = User::find(1);
$user->email = 'thinkphp@qq.com';
$user->save();
~~~
> `save`方法成功返回`true`,并只有当`before_update`事件返回`false`的时候返回`false`,有错误则会抛出异常。
如果要执行SQL函数更新,可以使用下面的方法。
~~~
$user = User::find(1);
$user->score = Db::raw('score+1');
$user->save();
~~~
## 字段过滤
默认情况下会过滤非数据表字段的数据,如果你通过外部提交赋值给模型,并且希望指定某些字段写入,可以使用:
~~~
$user = User::find(1);
// post数组中只有name和email字段会写入
$user->allowField(['name', 'email'])->save($_POST);
~~~
最佳用法是在传入模型数据之前就进行过滤,例如:
~~~
$user = User::find(1);
// post数组中只有name和email字段会写入
$data = Request::only(['name','email']);
$user->save($data);
~~~
## 批量更新数据
可以使用`saveAll`方法批量更新数据,只需要在批量更新的数据中包含主键即可,例如:
~~~
$user = new User;
$list = [
['id'=>1, 'name'=>'thinkphp', 'email'=>'thinkphp@qq.com'],
['id'=>2, 'name'=>'onethink', 'email'=>'onethink@qq.com']
];
$user->saveAll($list);
~~~
批量更新方法返回的是一个数据集对象。
> 批量更新仅能根据主键值进行更新,其它情况请自行处理。
## 直接更新(静态方法)
使用模型的静态`update`方法更新:
~~~
User::update(['name' => 'thinkphp'], ['id' => 1]);
~~~
> 模型的`update`方法返回模型的对象实例
如果你的第一个参数中包含主键数据,可以无需传入第二个参数(更新条件)
~~~
User::update(['name' => 'thinkphp', 'id' => 1]);
~~~
如果你需要只允许更新指定字段,可以使用
~~~
User::update(['name' => 'thinkphp', 'email' => 'thinkphp@qq.com'], ['id' => 1], ['name']);
~~~
上面的代码只会更新`name`字段的数据。
## 删除当前模型
删除模型数据,可以在查询后调用`delete`方法。
~~~
$user = User::find(1);
$user->delete();
~~~
> `delete`方法返回布尔值。
## 根据主键删除
或者直接调用静态方法(根据主键删除)
~~~
User::destroy(1);
// 支持批量删除多个数据
User::destroy([1,2,3]);
~~~
> 当`destroy`方法传入空值(包括空字符串和空数组)的时候不会做任何的数据删除操作,但传入0则是有效的。
## 条件删除
还支持使用闭包删除,例如:
~~~
User::destroy(function($query){
$query->where('id','>',10);
});
~~~
或者通过数据库类的查询条件删除
~~~
User::where('id','>',10)->delete();
~~~
> 直接调用数据库的`delete`方法的话无法调用模型事件。
## 关于删除的建议
> 删除的最佳实践原则是:如果删除当前模型数据,用`delete`方法,如果需要直接删除数据,使用`destroy`静态方法。
## 获取单个数据
获取单个数据的方法包括:
~~~
// 取出主键为1的数据
$user = User::find(1);
echo $user->name;
// 使用查询构造器查询满足条件的数据
$user = User::where('name', 'thinkphp')->find();
echo $user->name;
~~~
模型使用`find`方法查询,如果数据不存在返回`Null`,否则返回当前模型的对象实例。如果希望查询数据不存在则返回一个空模型,可以使用。
~~~
$user = User::findOrEmpty(1);
~~~
你可以用`isEmpty`方法来判断当前是否为一个空模型。
~~~
$user = User::where('name', 'thinkphp')->findOrEmpty();
if (!$user->isEmpty()) {
echo $user->name;
}
~~~
> 如果你是在模型内部获取数据,使用`$this->getAttr('name')`。
## 获取多个数据
取出多个数据:
~~~
// 根据主键获取多个数据
$list = User::select([1,2,3]);
// 对数据集进行遍历操作
foreach($list as $key=>$user){
echo $user->name;
}
~~~
要更多的查询支持,一样可以使用查询构造器:
~~~
// 使用查询构造器查询
$list = User::where('status', 1)->limit(3)->order('id', 'asc')->select();
foreach($list as $key=>$user){
echo $user->name;
}
~~~
> 查询构造器方式的查询可以支持更多的连贯操作,包括排序、数量限制等。
## 使用查询构造器
~~~
User::where('id',10)->find();
User::where('status',1)->order('id desc')->select();
User::where('status',1)->limit(10)->select();
~~~
使用查询构造器直接使用静态方法调用即可,无需先实例化模型。
### 获取某个字段或者某个列的值
~~~
// 获取某个用户的积分
User::where('id',10)->value('score');
// 获取某个列的所有值
User::where('status',1)->column('name');
// 以id为索引
User::where('status',1)->column('name','id');
~~~
> `value`和`column`方法返回的不再是一个模型对象实例,而是纯粹的值或者某个列的数组。
### 动态查询
支持数据库的动态查询方法,例如:
~~~
// 根据name字段查询用户
$user = User::getByName('thinkphp');
// 根据email字段查询用户
$user = User::getByEmail('thinkphp@qq.com');
~~~
### 聚合查询
同样在模型中也可以调用数据库的聚合方法查询,例如:
~~~
User::count();
User::where('status','>',0)->count();
User::where('status',1)->avg('score');
User::max('score');
~~~
注意,如果你的字段不是数字类型,是使用`max`/`min`的时候,需要加上第二个参数:`User::max('name', false);`。
## 关于查询的建议
> 模型查询的最佳实践原则是:在模型外部使用静态方法进行查询,内部使用动态方法查询,包括使用数据库的查询构造器。
- 搭建ThinkPHP6的开发环境
- 配置ThinkPHP6
- 必要的基础知识(basic)
- MVC开发模式
- 控制器(controller)
- 数据库(database)
- 模型(model)
- 模型关联(relation)
- 视图(view)
- Session
- Cookie
- 缓存(cache)
- 上传(upload)
- 验证器(validate)
- 验证码(captcha)
- 命令行(command)
- 服务器部署(deploy)
- 数据备份(backup)
- 数据同步(synchronization)
- 订阅服务(subscribe)
- PHP 易混淆知识点
- 助手函数
- MySQL规范
- Redis 规范
- office插件 phpoffice
- 拼音插件 pinyin
- 日期插件 datetime
- 消息插件 amqp
- 产品部署环境的搭建
- PDF 等杂项处理
- 文件上传
- 常用扩展
- flc/dysms
- 使用示例 ①
- 使用示例 ②
- qiniu/php-sdk
- 简介
- 使用示例
- 使用示例 2 ②
- liliuwei/thinkphp-jump
- 扩展介绍
- 下载扩展
- 使用方法
- topthink/think-captcha
- 安装扩展
- 验证码显示
- 更换验证码
- 验证码校验
- 验证码配置
- 自定义验证码
- phpoffice/phpspreadsheet
- 数据写入表格
- 读取表格数据
- topthink/think-queue
- 安装
- 自定义函数
- 任务类
- 带有日志的任务类