## 软删除:SoftDelete
>[info] 软删除其实就是:伪删除,没有真正的删除。正所谓,吃软饭的都是伪男一样的。
软删除是相对于硬删除来说的,所谓“软”是指删除以后,还可以恢复的。而“硬删除”则是物理删除,是真正的将数据从硬盘上擦掉了。
* * * * *
#### 1. 步骤:总的来说就二步
1. 在对应的模型类中做好相关的设置工作;
2. 在控制器中对该模型进行调用。
* * * * *
#### 2. 源码:/thinkphp/library/traits/model/SoftDelete.php
>[info] 源码中注释是本人单独添加,官方源码中并无这么多的注释
~~~
<?php
namespace traits\model;
trait SoftDelete
{
/**
* 判断当前实例是否被软删除
* @access public
* @return boolean
*/
public function trashed()
{
//获取软删除字段名称
$field = $this->getDeleteTimeField();
//如果当前数据对象的软删除字段为null,则已软删除
if (!empty($this->data[$field])) {
return true;
}
//否则返回false,表示没有被软删除
return false;
}
/**
* 查询软删除数据
* @access public
* @return \think\db\Query
*/
public static function withTrashed()
{
//实例化静态调用该方法的类,通常是子类:自定义的模型类,如Staff,User
$model = new static();
//getDeleteTimeField(true)表示当前为读操作:false表示写操作
$field = $model->getDeleteTimeField(true);
//在查结结果中,去掉已软删除的记录
return $model->db(false)->removeWhereField($field);
}
/**
* 只查询软删除数据
* @access public
* @return \think\db\Query
*/
public static function onlyTrashed()
{
//实例化静态调用该方法的类
$model = new static();
//获取软删除字段(true为读操作)
$field = $model->getDeleteTimeField(true);
//只输出删除字段不为空的数据,其实就是已经软删除的记录:理论上已删除
return $model->db(false)->where($field, 'exp', 'is not null');
}
/**
* 删除当前的记录
* 此方法会覆盖父类Model类中的delete方法,就是trait类的用处:多继承
* @access public
* @param bool $force 是否强制删除 true:硬删除
* @return integer
*/
public function delete($force = false)
{
if (false === $this->trigger('before_delete', $this)) {
return false;
}
$name = $this->getDeleteTimeField();
if (!$force) {
// 软删除
$this->change[] = $name;
$this->data[$name] = $this->autoWriteTimestamp($name);
$result = $this->isUpdate()->save();
} else {
$result = $this->db()->delete($this->data);
}
$this->trigger('after_delete', $this);
return $result;
}
/**
* 删除记录/软删除
* 该方法同样覆盖父类Model同名方法,用于静态调用
* @access public
* @param mixed $data 主键列表 支持闭包查询条件
* @param bool $force 是否强制删除
* @return integer 成功删除的记录数
*/
public static function destroy($data, $force = false)
{
//实例化当前调用类
$model = new static();
$query = $model->db();
if (is_array($data) && key($data) !== 0) {
$query->where($data);
$data = null;
} elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $query]);
$data = null;
} elseif (is_null($data)) {
return 0;
}
$resultSet = $query->select($data);
$count = 0;
if ($resultSet) {
foreach ($resultSet as $data) {
$result = $data->delete($force);
$count += $result;
}
}
return $count;
}
/**
* 恢复被软删除的记录
* @access public
* @param array $where 更新条件
* 参数为空,则恢复全部被软删除的数据
* @return integer
*/
public function restore($where = [])
{
$name = $this->getDeleteTimeField();
// 恢复删除
return $this->isUpdate()->save([$name => null], $where);
}
/**
* 查询默认不包含软删除数据
* @access protected
* @param \think\db\Query $query 查询对象
* @return void
*/
protected function base($query)
{
$field = $this->getDeleteTimeField(true);
$query->where($field, 'null');
}
/**
* 获取软删除字段
* @access public
* @param bool $read 是否查询操作 写操作的时候会自动去掉表别名
* @return string
*/
protected function getDeleteTimeField($read = false)
{
//获取软删除字段名称,如用户没有自定义,则设置成默认值:delete_time
$field = isset($this->deleteTime) ? $this->deleteTime : 'delete_time';
//判断字段名如果存在'.',则获取表名,并添加到字段前
if (!strpos($field, '.')) {
$field = $this->db(false)->getTable() . '.' . $field;
}
//写操作时,去掉表名
if (!$read && strpos($field, '.')) {
$array = explode('.', $field);
$field = array_pop($array);
}
//返回软删除字段名称
return $field;
}
}
~~~
>[warning] 阅读源码,发现有很多有用的方法,可以供模型类调用!其中的delete和destroy方法,直接拦截了调用Model类的对应方法,实现了软删除,理解这点很重要,这也是trait类的作用之一。
* * * * *
#### 3. 方法总结:
* 普通方法(public function )
| 序号 | 名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- | --- |
| 1 | trashed | 无 | 布尔值 | 判断当前实例是否被软删除 |
| 2 | delete | 布尔值 | 删除数量 | 删除当前的数据对象 |
| 3 | restore | 条件表达式 | 恢复数量 | 恢复被软删除的记录 |
* 静态方法(public static)
| 序号 | 名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- | --- |
| 1 | withTrashed | 无 | Query对象 | 查询软删除数据 |
| 2 | onlyTrashed | 无 | Query对象 | 只查询软删除数据 |
| 3 | destroy | 主键/表达多/闭包 | 删除数量 | 删除数据 |
* 保护方法(protected function)
| 序号 | 名称 | 参数 | 返回值 | 功能 |
| --- | --- | --- | --- | --- |
| 1 | base | Query对象 | 无定义 | 查询默认不包含软删除数据 |
| 2 | getDeleteTimeField| 布尔值 | 字段名称 | 获取软删除字段|
* * * * *
>[success] 下一节,我们以实例来详细讲解几个常用方法~~
- 前言[随时更新]
- 开发环境
- 1.Mac环境
- 2.windows环境
- 模型对象
- 1.创建模型对象
- 2.模型初始化
- 数据对象
- 1.定义数据对象
- 2.创建数据对象
- 1.data方法
- 2.setAttr方法
- 3.__set方法
- 4.查询数据对象
- 1.getData方法
- 2.getAttr方法
- 3.__get方法
- OOP难点总结
- 1.get_class( )实例讲解
- 2.get_called_class( )实例讲解
- 3.__call( )实例讲解
- 3.__callStatic( )实例讲解
- 4.call_user_func_array函数[重点]
- 5.普通方法与静态方法
- 6.在Model源码中的应用
- 7.new static 延迟静态绑定
- PHP标准化规范
- 查询数据
- 1.获取单条:get静态方法
- 2.获取单条:对象查询
- 3.获取多条:all静态方法
- 4.获取多条:对象查询
- 5.获取字段值:value方法
- 6.获取列值:column方法
- 7.动态查询:getBy字段名
- 8.助手函数:model查询
- 9.加载器:Loader类查询
- 10.数据库与模型查询对比
- 新增数据
- 1.sava方法
- 2.savaAll方法
- 3.create静态方法
- 4.insert静态调用
- 更新数据
- 1.单条更新:save方法
- 2.批量更新:saveAll方法
- 3.静态更新:update方法
- 4.查询类Query直接更新
- 5. 闭包更新
- 删除数据
- 1.删除当前记录:delete
- 2.静态条件删除:destory
- 获取器
- 1.模型方法:set属性Attr
- 修改器
- 1.set属性Attr
- 时间戳
- 1.MySQL中日期类型复习
- 2.时间戳功能详解
- 软删除[重点]
- 1.traits详解[选学内容]
- 2.SoftDelet类源码分析
- 3. delete实例删除
- 4.destroy条件删除
- 5.restore恢复数据
- 类型转换
- 1. 规则设置
- 2. 实例演示
- 查询范围
- 1. 基本概念
- 2.实例演示